diff --git a/.circleci/config.yml b/.circleci/config.yml index 467aabc59..090d1356e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,10 +3,10 @@ version: 2.1 executors: node-browsers: docker: - - image: circleci/node:16-browsers + - image: cimg/node:16.20-browsers node-browsers-medium-plus: docker: - - image: circleci/node:16-browsers + - image: cimg/node:16.20-browsers resource_class: medium+ environment: NODE_OPTIONS: --max_old_space_size=2048 diff --git a/.circleci/scripts/chrome-install.sh b/.circleci/scripts/chrome-install.sh index cc83d987e..450293197 100755 --- a/.circleci/scripts/chrome-install.sh +++ b/.circleci/scripts/chrome-install.sh @@ -4,6 +4,8 @@ set -e set -u set -o pipefail +sudo apt-get update + # To get the latest version, see CHROME_VERSION='111.0.5563.64-1' CHROME_BINARY="google-chrome-stable_${CHROME_VERSION}_amd64.deb" diff --git a/.circleci/scripts/firefox-install.sh b/.circleci/scripts/firefox-install.sh index be31f8bf4..4cb30ec32 100755 --- a/.circleci/scripts/firefox-install.sh +++ b/.circleci/scripts/firefox-install.sh @@ -9,10 +9,6 @@ FIREFOX_BINARY="firefox-${FIREFOX_VERSION}.tar.bz2" FIREFOX_BINARY_URL="https://ftp.mozilla.org/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/${FIREFOX_BINARY}" FIREFOX_PATH='/opt/firefox' -printf '%s\n' "Removing old Firefox installation" - -sudo rm -r "${FIREFOX_PATH}" - printf '%s\n' "Downloading & installing Firefox ${FIREFOX_VERSION}" wget --quiet --show-progress -O- "${FIREFOX_BINARY_URL}" | sudo tar xj -C /opt diff --git a/.depcheckrc.yml b/.depcheckrc.yml index a67a8263e..c2e8cd6fa 100644 --- a/.depcheckrc.yml +++ b/.depcheckrc.yml @@ -10,6 +10,14 @@ ignores: - '@fortawesome/fontawesome-free' - 'punycode' + # + # snaps flask deps + # + - '@metamask/rpc-methods-flask' + - '@metamask/snaps-controllers-flask' + - '@metamask/snaps-ui-flask' + - '@metamask/snaps-utils-flask' + # # dev deps # diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bb69a3863..546f26ec8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,20 +1,22 @@ # Lines starting with '#' are comments. # Each line is a file pattern followed by one or more owners. # Owners bear a responsibility to the organization and the users of this -# application. Repository administrators have the ability to merge pull -# requests that have not yet received the requisite reviews as outlined -# in this file. Do not force merge any PR without confidence that it -# follows all policies or without full understanding of the impact of +# application. Repository administrators have the ability to merge pull +# requests that have not yet received the requisite reviews as outlined +# in this file. Do not force merge any PR without confidence that it +# follows all policies or without full understanding of the impact of # those changes on build, release and publishing outcomes. * @MetaMask/extension-devs +**/snaps/** @MetaMask/snaps-devs +**/flask/** @MetaMask/snaps-devs development/ @MetaMask/extension-devs @kumavis -lavamoat/ @MetaMask/supply-chain +lavamoat/ @MetaMask/extension-devs @MetaMask/supply-chain @MetaMask/snaps-devs # The .circleci/ folder instructs Circle CI on the process by which it # should test, build and publish releases of our application. Due to the # impact that changes to the files contained within this folder may have -# on our releases, only those with the knowledge and responsibility to +# on our releases, only those with the knowledge and responsibility to # publish libraries under the MetaMask name may approve those changes. # Note to reviewers: We employ the use of CircleCI "Orbs", which are # remotely hosted sections of CircleCI configuration and scripts, to diff --git a/.github/workflows/do-not-merge.yml b/.github/workflows/do-not-merge.yml new file mode 100644 index 000000000..1315a282b --- /dev/null +++ b/.github/workflows/do-not-merge.yml @@ -0,0 +1,17 @@ +# Fails the pull request if it has the "DO-NOT-MERGE" label + +name: Check "DO-NOT-MERGE" label + +on: + pull_request: + types: [opened, reopened, labeled, unlabeled, synchronize] + +jobs: + do-not-merge: + runs-on: ubuntu-latest + if: ${{ contains(github.event.pull_request.labels.*.name, 'DO-NOT-MERGE') }} + steps: + - name: 'Check for label "DO-NOT-MERGE"' + run: | + echo 'This check fails PRs with the "DO-NOT-MERGE" label to block merging' + exit 1 diff --git a/.github/workflows/fitness-functions.yml b/.github/workflows/fitness-functions.yml index 7549be6b4..20efbf90e 100644 --- a/.github/workflows/fitness-functions.yml +++ b/.github/workflows/fitness-functions.yml @@ -11,18 +11,24 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Use Node.js uses: actions/setup-node@v3 with: node-version: '16' + - name: Install dependencies + run: yarn + - name: Run fitness functions env: - HEAD_REF: ${{ github.event.pull_request.head.ref }} BASE_REF: ${{ github.event.pull_request.base.ref }} run: | - # git fetch origin $HEAD_REF - # git fetch origin $BASE_REF - # git diff origin/$BASE_REF origin/$HEAD_REF -- . ':(exclude)development/fitness-functions/*' > diff - # npm run fitness-functions -- "ci" "./diff" + # The following command generates a diff of changes between the common + # ancestor of $BASE_REF and HEAD, and the current commit (HEAD), for + # files in the current directory and its subdirectories. The output is + # then saved to a file called "diff". + git diff "$(git merge-base "origin/$BASE_REF" HEAD)" HEAD -- . > ./diff + npm run fitness-functions -- "ci" "./diff" \ No newline at end of file diff --git a/.iyarc b/.iyarc index 79536d383..bc4ac2498 100644 --- a/.iyarc +++ b/.iyarc @@ -6,16 +6,6 @@ GHSA-257v-vj4p-3w2h # 7.1.1 and is included only via remote-redux-devtools which is a devDependency GHSA-6fc8-4gx4-v693 -# yarn npm audit reports on a fast-json-patch version < 3.1.1 but due to patch -# resolution, the only version of fast-json-patch that we use is 3.1.1. We also -# have 2.2.1 installed but it is a dev only dependency. The "violation" reports -# smart-transacton-controller as the culprit but if you run -# `yarn info -A -R dependents fast-json-patch` you can see that only 2.2.1 and -# 3.3.1 are installed and that smart-transaction-controller resolves to the -# patched version of 3.3.1. We can remove this once the -# smart-transaction-controller updates its dependency. -GHSA-8gh8-hqwg-xf34 - # request library is subject to SSRF. # addressed by temporary patch in .yarn/patches/request-npm-2.88.2-f4a57c72c4.patch GHSA-p8p7-x288-28g6 diff --git a/.metamaskrc.dist b/.metamaskrc.dist index d430e090f..d00289cdb 100644 --- a/.metamaskrc.dist +++ b/.metamaskrc.dist @@ -1,11 +1,15 @@ ; Extra environment variables -PASSWORD=METAMASK PASSWORD +; Defaults are set in builds.yml + +; This variable is required INFURA_PROJECT_ID=00000000000 -SEGMENT_WRITE_KEY= -SWAPS_USE_DEV_APIS= -PORTFOLIO_URL= -TRANSACTION_SECURITY_PROVIDER= -MULTICHAIN= + +;PASSWORD=METAMASK PASSWORD +,SEGMENT_WRITE_KEY= +;SWAPS_USE_DEV_APIS= +;PORTFOLIO_URL= +;TRANSACTION_SECURITY_PROVIDER= +;MULTICHAIN= ; Set this to test changes to the phishing warning page. -PHISHING_WARNING_PAGE_URL= +;PHISHING_WARNING_PAGE_URL= diff --git a/.storybook/test-data.js b/.storybook/test-data.js index 496094a91..48013e303 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -599,7 +599,7 @@ const state = { connectedStatusPopoverHasBeenShown: true, swapsWelcomeMessageHasBeenShown: true, defaultHomeActiveTabName: 'Assets', - provider: { + providerConfig: { type: 'goerli', ticker: 'ETH', nickname: '', diff --git a/.yarn/patches/@eslint-eslintrc-npm-1.3.0-1f3c51be25.patch b/.yarn/patches/@eslint-eslintrc-npm-1.3.0-1f3c51be25.patch deleted file mode 100644 index e2db09fb6..000000000 --- a/.yarn/patches/@eslint-eslintrc-npm-1.3.0-1f3c51be25.patch +++ /dev/null @@ -1,59 +0,0 @@ -diff --git a/dist/eslintrc.cjs b/dist/eslintrc.cjs -index 8b07ba16516e5b4d21663c7c28f905b933244e3f..524919dcce78e507121e5a6ff0d0c9d4f118580e 100644 ---- a/dist/eslintrc.cjs -+++ b/dist/eslintrc.cjs -@@ -4,7 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true }); - - var debugOrig = require('debug'); - var fs = require('fs'); --var importFresh = require('import-fresh'); - var Module = require('module'); - var path = require('path'); - var stripComments = require('strip-json-comments'); -@@ -20,7 +19,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau - - var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig); - var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); --var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh); - var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module); - var path__default = /*#__PURE__*/_interopDefaultLegacy(path); - var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments); -@@ -2556,7 +2554,7 @@ function loadLegacyConfigFile(filePath) { - function loadJSConfigFile(filePath) { - debug$2(`Loading JS config file: ${filePath}`); - try { -- return importFresh__default["default"](filePath); -+ return require$1(filePath); - } catch (e) { - debug$2(`Error reading JavaScript file: ${filePath}`); - e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`; -diff --git a/dist/eslintrc.cjs.map b/dist/eslintrc.cjs.map -index 246d9f205dfe361d37095040993bad90adcf34ca..8ee97a27bdf09f1021a077b9f308ea09f96d956a 100644 ---- a/dist/eslintrc.cjs.map -+++ b/dist/eslintrc.cjs.map -@@ -1 +1 @@ --{"version":3,"file":"eslintrc.cjs","sources":["../lib/config-array/ignore-pattern.js","../lib/config-array/extracted-config.js","../lib/config-array/config-array.js","../lib/config-array/config-dependency.js","../lib/config-array/override-tester.js","../lib/config-array/index.js","../lib/shared/config-ops.js","../lib/shared/deprecation-warnings.js","../lib/shared/ajv.js","../conf/config-schema.js","../conf/environments.js","../lib/shared/config-validator.js","../lib/shared/naming.js","../lib/shared/relative-module-resolver.js","../lib/config-array-factory.js","../lib/cascading-config-array-factory.js","../lib/flat-compat.js","../lib/index.js"],"sourcesContent":["/**\n * @fileoverview `IgnorePattern` class.\n *\n * `IgnorePattern` class has the set of glob patterns and the base path.\n *\n * It provides two static methods.\n *\n * - `IgnorePattern.createDefaultIgnore(cwd)`\n * Create the default predicate function.\n * - `IgnorePattern.createIgnore(ignorePatterns)`\n * Create the predicate function from multiple `IgnorePattern` objects.\n *\n * It provides two properties and a method.\n *\n * - `patterns`\n * The glob patterns that ignore to lint.\n * - `basePath`\n * The base path of the glob patterns. If absolute paths existed in the\n * glob patterns, those are handled as relative paths to the base path.\n * - `getPatternsRelativeTo(basePath)`\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n *\n * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes\n * `ignorePatterns` properties.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport ignore from \"ignore\";\nimport debugOrig from \"debug\";\n\nconst debug = debugOrig(\"eslintrc:ignore-pattern\");\n\n/** @typedef {ReturnType} Ignore */\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the path to the common ancestor directory of given paths.\n * @param {string[]} sourcePaths The paths to calculate the common ancestor.\n * @returns {string} The path to the common ancestor directory.\n */\nfunction getCommonAncestorPath(sourcePaths) {\n let result = sourcePaths[0];\n\n for (let i = 1; i < sourcePaths.length; ++i) {\n const a = result;\n const b = sourcePaths[i];\n\n // Set the shorter one (it's the common ancestor if one includes the other).\n result = a.length < b.length ? a : b;\n\n // Set the common ancestor.\n for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {\n if (a[j] !== b[j]) {\n result = a.slice(0, lastSepPos);\n break;\n }\n if (a[j] === path.sep) {\n lastSepPos = j;\n }\n }\n }\n\n let resolvedResult = result || path.sep;\n\n // if Windows common ancestor is root of drive must have trailing slash to be absolute.\n if (resolvedResult && resolvedResult.endsWith(\":\") && process.platform === \"win32\") {\n resolvedResult += path.sep;\n }\n return resolvedResult;\n}\n\n/**\n * Make relative path.\n * @param {string} from The source path to get relative path.\n * @param {string} to The destination path to get relative path.\n * @returns {string} The relative path.\n */\nfunction relative(from, to) {\n const relPath = path.relative(from, to);\n\n if (path.sep === \"/\") {\n return relPath;\n }\n return relPath.split(path.sep).join(\"/\");\n}\n\n/**\n * Get the trailing slash if existed.\n * @param {string} filePath The path to check.\n * @returns {string} The trailing slash if existed.\n */\nfunction dirSuffix(filePath) {\n const isDir = (\n filePath.endsWith(path.sep) ||\n (process.platform === \"win32\" && filePath.endsWith(\"/\"))\n );\n\n return isDir ? \"/\" : \"\";\n}\n\nconst DefaultPatterns = Object.freeze([\"/**/node_modules/*\"]);\nconst DotPatterns = Object.freeze([\".*\", \"!.eslintrc.*\", \"!../\"]);\n\n//------------------------------------------------------------------------------\n// Public\n//------------------------------------------------------------------------------\n\nclass IgnorePattern {\n\n /**\n * The default patterns.\n * @type {string[]}\n */\n static get DefaultPatterns() {\n return DefaultPatterns;\n }\n\n /**\n * Create the default predicate function.\n * @param {string} cwd The current working directory.\n * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createDefaultIgnore(cwd) {\n return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);\n }\n\n /**\n * Create the predicate function from multiple `IgnorePattern` objects.\n * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.\n * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createIgnore(ignorePatterns) {\n debug(\"Create with: %o\", ignorePatterns);\n\n const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));\n const patterns = [].concat(\n ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))\n );\n const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);\n const dotIg = ignore({ allowRelativePaths: true }).add(patterns);\n\n debug(\" processed: %o\", { basePath, patterns });\n\n return Object.assign(\n (filePath, dot = false) => {\n assert(path.isAbsolute(filePath), \"'filePath' should be an absolute path.\");\n const relPathRaw = relative(basePath, filePath);\n const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));\n const adoptedIg = dot ? dotIg : ig;\n const result = relPath !== \"\" && adoptedIg.ignores(relPath);\n\n debug(\"Check\", { filePath, dot, relativePath: relPath, result });\n return result;\n },\n { basePath, patterns }\n );\n }\n\n /**\n * Initialize a new `IgnorePattern` instance.\n * @param {string[]} patterns The glob patterns that ignore to lint.\n * @param {string} basePath The base path of `patterns`.\n */\n constructor(patterns, basePath) {\n assert(path.isAbsolute(basePath), \"'basePath' should be an absolute path.\");\n\n /**\n * The glob patterns that ignore to lint.\n * @type {string[]}\n */\n this.patterns = patterns;\n\n /**\n * The base path of `patterns`.\n * @type {string}\n */\n this.basePath = basePath;\n\n /**\n * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.\n *\n * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.\n * It's `false` as-is for `ignorePatterns` property in config files.\n * @type {boolean}\n */\n this.loose = false;\n }\n\n /**\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n * @param {string} newBasePath The base path.\n * @returns {string[]} Modifired patterns.\n */\n getPatternsRelativeTo(newBasePath) {\n assert(path.isAbsolute(newBasePath), \"'newBasePath' should be an absolute path.\");\n const { basePath, loose, patterns } = this;\n\n if (newBasePath === basePath) {\n return patterns;\n }\n const prefix = `/${relative(newBasePath, basePath)}`;\n\n return patterns.map(pattern => {\n const negative = pattern.startsWith(\"!\");\n const head = negative ? \"!\" : \"\";\n const body = negative ? pattern.slice(1) : pattern;\n\n if (body.startsWith(\"/\") || body.startsWith(\"../\")) {\n return `${head}${prefix}${body}`;\n }\n return loose ? pattern : `${head}${prefix}/**/${body}`;\n });\n }\n}\n\nexport { IgnorePattern };\n","/**\n * @fileoverview `ExtractedConfig` class.\n *\n * `ExtractedConfig` class expresses a final configuration for a specific file.\n *\n * It provides one method.\n *\n * - `toCompatibleObjectAsConfigFileContent()`\n * Convert this configuration to the compatible object as the content of\n * config files. It converts the loaded parser and plugins to strings.\n * `CLIEngine#getConfigForFile(filePath)` method uses this method.\n *\n * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.\n *\n * @author Toru Nagashima \n */\n\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n// For VSCode intellisense\n/** @typedef {import(\"../../shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").SeverityConf} SeverityConf */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n\n/**\n * Check if `xs` starts with `ys`.\n * @template T\n * @param {T[]} xs The array to check.\n * @param {T[]} ys The array that may be the first part of `xs`.\n * @returns {boolean} `true` if `xs` starts with `ys`.\n */\nfunction startsWith(xs, ys) {\n return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);\n}\n\n/**\n * The class for extracted config data.\n */\nclass ExtractedConfig {\n constructor() {\n\n /**\n * The config name what `noInlineConfig` setting came from.\n * @type {string}\n */\n this.configNameOfNoInlineConfig = \"\";\n\n /**\n * Environments.\n * @type {Record}\n */\n this.env = {};\n\n /**\n * Global variables.\n * @type {Record}\n */\n this.globals = {};\n\n /**\n * The glob patterns that ignore to lint.\n * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}\n */\n this.ignores = void 0;\n\n /**\n * The flag that disables directive comments.\n * @type {boolean|undefined}\n */\n this.noInlineConfig = void 0;\n\n /**\n * Parser definition.\n * @type {DependentParser|null}\n */\n this.parser = null;\n\n /**\n * Options for the parser.\n * @type {Object}\n */\n this.parserOptions = {};\n\n /**\n * Plugin definitions.\n * @type {Record}\n */\n this.plugins = {};\n\n /**\n * Processor ID.\n * @type {string|null}\n */\n this.processor = null;\n\n /**\n * The flag that reports unused `eslint-disable` directive comments.\n * @type {boolean|undefined}\n */\n this.reportUnusedDisableDirectives = void 0;\n\n /**\n * Rule settings.\n * @type {Record}\n */\n this.rules = {};\n\n /**\n * Shared settings.\n * @type {Object}\n */\n this.settings = {};\n }\n\n /**\n * Convert this config to the compatible object as a config file content.\n * @returns {ConfigData} The converted object.\n */\n toCompatibleObjectAsConfigFileContent() {\n const {\n /* eslint-disable no-unused-vars */\n configNameOfNoInlineConfig: _ignore1,\n processor: _ignore2,\n /* eslint-enable no-unused-vars */\n ignores,\n ...config\n } = this;\n\n config.parser = config.parser && config.parser.filePath;\n config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();\n config.ignorePatterns = ignores ? ignores.patterns : [];\n\n // Strip the default patterns from `ignorePatterns`.\n if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {\n config.ignorePatterns =\n config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);\n }\n\n return config;\n }\n}\n\nexport { ExtractedConfig };\n","/**\n * @fileoverview `ConfigArray` class.\n *\n * `ConfigArray` class expresses the full of a configuration. It has the entry\n * config file, base config files that were extended, loaded parsers, and loaded\n * plugins.\n *\n * `ConfigArray` class provides three properties and two methods.\n *\n * - `pluginEnvironments`\n * - `pluginProcessors`\n * - `pluginRules`\n * The `Map` objects that contain the members of all plugins that this\n * config array contains. Those map objects don't have mutation methods.\n * Those keys are the member ID such as `pluginId/memberName`.\n * - `isRoot()`\n * If `true` then this configuration has `root:true` property.\n * - `extractConfig(filePath)`\n * Extract the final configuration for a given file. This means merging\n * every config array element which that `criteria` property matched. The\n * `filePath` argument must be an absolute path.\n *\n * `ConfigArrayFactory` provides the loading logic of config files.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").RuleConf} RuleConf */\n/** @typedef {import(\"../../shared/types\").Rule} Rule */\n/** @typedef {import(\"../../shared/types\").Plugin} Plugin */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {import(\"./override-tester\")[\"OverrideTester\"]} OverrideTester */\n\n/**\n * @typedef {Object} ConfigArrayElement\n * @property {string} name The name of this config element.\n * @property {string} filePath The path to the source file of this config element.\n * @property {InstanceType|null} criteria The tester for the `files` and `excludedFiles` of this config element.\n * @property {Record|undefined} env The environment settings.\n * @property {Record|undefined} globals The global variable settings.\n * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.\n * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.\n * @property {DependentParser|undefined} parser The parser loader.\n * @property {Object|undefined} parserOptions The parser options.\n * @property {Record|undefined} plugins The plugin loaders.\n * @property {string|undefined} processor The processor name to refer plugin's processor.\n * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.\n * @property {boolean|undefined} root The flag to express root.\n * @property {Record|undefined} rules The rule settings\n * @property {Object|undefined} settings The shared settings.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The element type.\n */\n\n/**\n * @typedef {Object} ConfigArrayInternalSlots\n * @property {Map} cache The cache to extract configs.\n * @property {ReadonlyMap|null} envMap The map from environment ID to environment definition.\n * @property {ReadonlyMap|null} processorMap The map from processor ID to environment definition.\n * @property {ReadonlyMap|null} ruleMap The map from rule ID to rule definition.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new class extends WeakMap {\n get(key) {\n let value = super.get(key);\n\n if (!value) {\n value = {\n cache: new Map(),\n envMap: null,\n processorMap: null,\n ruleMap: null\n };\n super.set(key, value);\n }\n\n return value;\n }\n}();\n\n/**\n * Get the indices which are matched to a given file.\n * @param {ConfigArrayElement[]} elements The elements.\n * @param {string} filePath The path to a target file.\n * @returns {number[]} The indices.\n */\nfunction getMatchedIndices(elements, filePath) {\n const indices = [];\n\n for (let i = elements.length - 1; i >= 0; --i) {\n const element = elements[i];\n\n if (!element.criteria || (filePath && element.criteria.test(filePath))) {\n indices.push(i);\n }\n }\n\n return indices;\n}\n\n/**\n * Check if a value is a non-null object.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is a non-null object.\n */\nfunction isNonNullObject(x) {\n return typeof x === \"object\" && x !== null;\n}\n\n/**\n * Merge two objects.\n *\n * Assign every property values of `y` to `x` if `x` doesn't have the property.\n * If `x`'s property value is an object, it does recursive.\n * @param {Object} target The destination to merge\n * @param {Object|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeWithoutOverwrite(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n\n if (isNonNullObject(target[key])) {\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (target[key] === void 0) {\n if (isNonNullObject(source[key])) {\n target[key] = Array.isArray(source[key]) ? [] : {};\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (source[key] !== void 0) {\n target[key] = source[key];\n }\n }\n }\n}\n\n/**\n * The error for plugin conflicts.\n */\nclass PluginConflictError extends Error {\n\n /**\n * Initialize this error object.\n * @param {string} pluginId The plugin ID.\n * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.\n */\n constructor(pluginId, plugins) {\n super(`Plugin \"${pluginId}\" was conflicted between ${plugins.map(p => `\"${p.importerName}\"`).join(\" and \")}.`);\n this.messageTemplate = \"plugin-conflict\";\n this.messageData = { pluginId, plugins };\n }\n}\n\n/**\n * Merge plugins.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergePlugins(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetValue = target[key];\n const sourceValue = source[key];\n\n // Adopt the plugin which was found at first.\n if (targetValue === void 0) {\n if (sourceValue.error) {\n throw sourceValue.error;\n }\n target[key] = sourceValue;\n } else if (sourceValue.filePath !== targetValue.filePath) {\n throw new PluginConflictError(key, [\n {\n filePath: targetValue.filePath,\n importerName: targetValue.importerName\n },\n {\n filePath: sourceValue.filePath,\n importerName: sourceValue.importerName\n }\n ]);\n }\n }\n}\n\n/**\n * Merge rule configs.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeRuleConfigs(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetDef = target[key];\n const sourceDef = source[key];\n\n // Adopt the rule config which was found at first.\n if (targetDef === void 0) {\n if (Array.isArray(sourceDef)) {\n target[key] = [...sourceDef];\n } else {\n target[key] = [sourceDef];\n }\n\n /*\n * If the first found rule config is severity only and the current rule\n * config has options, merge the severity and the options.\n */\n } else if (\n targetDef.length === 1 &&\n Array.isArray(sourceDef) &&\n sourceDef.length >= 2\n ) {\n targetDef.push(...sourceDef.slice(1));\n }\n }\n}\n\n/**\n * Create the extracted config.\n * @param {ConfigArray} instance The config elements.\n * @param {number[]} indices The indices to use.\n * @returns {ExtractedConfig} The extracted config.\n */\nfunction createConfig(instance, indices) {\n const config = new ExtractedConfig();\n const ignorePatterns = [];\n\n // Merge elements.\n for (const index of indices) {\n const element = instance[index];\n\n // Adopt the parser which was found at first.\n if (!config.parser && element.parser) {\n if (element.parser.error) {\n throw element.parser.error;\n }\n config.parser = element.parser;\n }\n\n // Adopt the processor which was found at first.\n if (!config.processor && element.processor) {\n config.processor = element.processor;\n }\n\n // Adopt the noInlineConfig which was found at first.\n if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {\n config.noInlineConfig = element.noInlineConfig;\n config.configNameOfNoInlineConfig = element.name;\n }\n\n // Adopt the reportUnusedDisableDirectives which was found at first.\n if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {\n config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;\n }\n\n // Collect ignorePatterns\n if (element.ignorePattern) {\n ignorePatterns.push(element.ignorePattern);\n }\n\n // Merge others.\n mergeWithoutOverwrite(config.env, element.env);\n mergeWithoutOverwrite(config.globals, element.globals);\n mergeWithoutOverwrite(config.parserOptions, element.parserOptions);\n mergeWithoutOverwrite(config.settings, element.settings);\n mergePlugins(config.plugins, element.plugins);\n mergeRuleConfigs(config.rules, element.rules);\n }\n\n // Create the predicate function for ignore patterns.\n if (ignorePatterns.length > 0) {\n config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());\n }\n\n return config;\n}\n\n/**\n * Collect definitions.\n * @template T, U\n * @param {string} pluginId The plugin ID for prefix.\n * @param {Record} defs The definitions to collect.\n * @param {Map} map The map to output.\n * @param {function(T): U} [normalize] The normalize function for each value.\n * @returns {void}\n */\nfunction collect(pluginId, defs, map, normalize) {\n if (defs) {\n const prefix = pluginId && `${pluginId}/`;\n\n for (const [key, value] of Object.entries(defs)) {\n map.set(\n `${prefix}${key}`,\n normalize ? normalize(value) : value\n );\n }\n }\n}\n\n/**\n * Normalize a rule definition.\n * @param {Function|Rule} rule The rule definition to normalize.\n * @returns {Rule} The normalized rule definition.\n */\nfunction normalizePluginRule(rule) {\n return typeof rule === \"function\" ? { create: rule } : rule;\n}\n\n/**\n * Delete the mutation methods from a given map.\n * @param {Map} map The map object to delete.\n * @returns {void}\n */\nfunction deleteMutationMethods(map) {\n Object.defineProperties(map, {\n clear: { configurable: true, value: void 0 },\n delete: { configurable: true, value: void 0 },\n set: { configurable: true, value: void 0 }\n });\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArrayElement[]} elements The config elements.\n * @param {ConfigArrayInternalSlots} slots The internal slots.\n * @returns {void}\n */\nfunction initPluginMemberMaps(elements, slots) {\n const processed = new Set();\n\n slots.envMap = new Map();\n slots.processorMap = new Map();\n slots.ruleMap = new Map();\n\n for (const element of elements) {\n if (!element.plugins) {\n continue;\n }\n\n for (const [pluginId, value] of Object.entries(element.plugins)) {\n const plugin = value.definition;\n\n if (!plugin || processed.has(pluginId)) {\n continue;\n }\n processed.add(pluginId);\n\n collect(pluginId, plugin.environments, slots.envMap);\n collect(pluginId, plugin.processors, slots.processorMap);\n collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);\n }\n }\n\n deleteMutationMethods(slots.envMap);\n deleteMutationMethods(slots.processorMap);\n deleteMutationMethods(slots.ruleMap);\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArray} instance The config elements.\n * @returns {ConfigArrayInternalSlots} The extracted config.\n */\nfunction ensurePluginMemberMaps(instance) {\n const slots = internalSlotsMap.get(instance);\n\n if (!slots.ruleMap) {\n initPluginMemberMaps(instance, slots);\n }\n\n return slots;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The Config Array.\n *\n * `ConfigArray` instance contains all settings, parsers, and plugins.\n * You need to call `ConfigArray#extractConfig(filePath)` method in order to\n * extract, merge and get only the config data which is related to an arbitrary\n * file.\n * @extends {Array}\n */\nclass ConfigArray extends Array {\n\n /**\n * Get the plugin environments.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin environments.\n */\n get pluginEnvironments() {\n return ensurePluginMemberMaps(this).envMap;\n }\n\n /**\n * Get the plugin processors.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin processors.\n */\n get pluginProcessors() {\n return ensurePluginMemberMaps(this).processorMap;\n }\n\n /**\n * Get the plugin rules.\n * The returned map cannot be mutated.\n * @returns {ReadonlyMap} The plugin rules.\n */\n get pluginRules() {\n return ensurePluginMemberMaps(this).ruleMap;\n }\n\n /**\n * Check if this config has `root` flag.\n * @returns {boolean} `true` if this config array is root.\n */\n isRoot() {\n for (let i = this.length - 1; i >= 0; --i) {\n const root = this[i].root;\n\n if (typeof root === \"boolean\") {\n return root;\n }\n }\n return false;\n }\n\n /**\n * Extract the config data which is related to a given file.\n * @param {string} filePath The absolute path to the target file.\n * @returns {ExtractedConfig} The extracted config data.\n */\n extractConfig(filePath) {\n const { cache } = internalSlotsMap.get(this);\n const indices = getMatchedIndices(this, filePath);\n const cacheKey = indices.join(\",\");\n\n if (!cache.has(cacheKey)) {\n cache.set(cacheKey, createConfig(this, indices));\n }\n\n return cache.get(cacheKey);\n }\n\n /**\n * Check if a given path is an additional lint target.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the file is an additional lint target.\n */\n isAdditionalTargetPath(filePath) {\n for (const { criteria, type } of this) {\n if (\n type === \"config\" &&\n criteria &&\n !criteria.endsWithWildcard &&\n criteria.test(filePath)\n ) {\n return true;\n }\n }\n return false;\n }\n}\n\n/**\n * Get the used extracted configs.\n * CLIEngine will use this method to collect used deprecated rules.\n * @param {ConfigArray} instance The config array object to get.\n * @returns {ExtractedConfig[]} The used extracted configs.\n * @private\n */\nfunction getUsedExtractedConfigs(instance) {\n const { cache } = internalSlotsMap.get(instance);\n\n return Array.from(cache.values());\n}\n\n\nexport {\n ConfigArray,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview `ConfigDependency` class.\n *\n * `ConfigDependency` class expresses a loaded parser or plugin.\n *\n * If the parser or plugin was loaded successfully, it has `definition` property\n * and `filePath` property. Otherwise, it has `error` property.\n *\n * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it\n * omits `definition` property.\n *\n * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers\n * or plugins.\n *\n * @author Toru Nagashima \n */\n\nimport util from \"util\";\n\n/**\n * The class is to store parsers or plugins.\n * This class hides the loaded object from `JSON.stringify()` and `console.log`.\n * @template T\n */\nclass ConfigDependency {\n\n /**\n * Initialize this instance.\n * @param {Object} data The dependency data.\n * @param {T} [data.definition] The dependency if the loading succeeded.\n * @param {Error} [data.error] The error object if the loading failed.\n * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.\n * @param {string} data.id The ID of this dependency.\n * @param {string} data.importerName The name of the config file which loads this dependency.\n * @param {string} data.importerPath The path to the config file which loads this dependency.\n */\n constructor({\n definition = null,\n error = null,\n filePath = null,\n id,\n importerName,\n importerPath\n }) {\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {T|null}\n */\n this.definition = definition;\n\n /**\n * The error object if the loading failed.\n * @type {Error|null}\n */\n this.error = error;\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {string|null}\n */\n this.filePath = filePath;\n\n /**\n * The ID of this dependency.\n * @type {string}\n */\n this.id = id;\n\n /**\n * The name of the config file which loads this dependency.\n * @type {string}\n */\n this.importerName = importerName;\n\n /**\n * The path to the config file which loads this dependency.\n * @type {string}\n */\n this.importerPath = importerPath;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n const obj = this[util.inspect.custom]();\n\n // Display `error.message` (`Error#message` is unenumerable).\n if (obj.error instanceof Error) {\n obj.error = { ...obj.error, message: obj.error.message };\n }\n\n return obj;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n const {\n definition: _ignore, // eslint-disable-line no-unused-vars\n ...obj\n } = this;\n\n return obj;\n }\n}\n\n/** @typedef {ConfigDependency} DependentParser */\n/** @typedef {ConfigDependency} DependentPlugin */\n\nexport { ConfigDependency };\n","/**\n * @fileoverview `OverrideTester` class.\n *\n * `OverrideTester` class handles `files` property and `excludedFiles` property\n * of `overrides` config.\n *\n * It provides one method.\n *\n * - `test(filePath)`\n * Test if a file path matches the pair of `files` property and\n * `excludedFiles` property. The `filePath` argument must be an absolute\n * path.\n *\n * `ConfigArrayFactory` creates `OverrideTester` objects when it processes\n * `overrides` properties.\n *\n * @author Toru Nagashima \n */\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport util from \"util\";\nimport minimatch from \"minimatch\";\n\nconst { Minimatch } = minimatch;\n\nconst minimatchOpts = { dot: true, matchBase: true };\n\n/**\n * @typedef {Object} Pattern\n * @property {InstanceType[] | null} includes The positive matchers.\n * @property {InstanceType[] | null} excludes The negative matchers.\n */\n\n/**\n * Normalize a given pattern to an array.\n * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.\n * @returns {string[]|null} Normalized patterns.\n * @private\n */\nfunction normalizePatterns(patterns) {\n if (Array.isArray(patterns)) {\n return patterns.filter(Boolean);\n }\n if (typeof patterns === \"string\" && patterns) {\n return [patterns];\n }\n return [];\n}\n\n/**\n * Create the matchers of given patterns.\n * @param {string[]} patterns The patterns.\n * @returns {InstanceType[] | null} The matchers.\n */\nfunction toMatcher(patterns) {\n if (patterns.length === 0) {\n return null;\n }\n return patterns.map(pattern => {\n if (/^\\.[/\\\\]/u.test(pattern)) {\n return new Minimatch(\n pattern.slice(2),\n\n // `./*.js` should not match with `subdir/foo.js`\n { ...minimatchOpts, matchBase: false }\n );\n }\n return new Minimatch(pattern, minimatchOpts);\n });\n}\n\n/**\n * Convert a given matcher to string.\n * @param {Pattern} matchers The matchers.\n * @returns {string} The string expression of the matcher.\n */\nfunction patternToJson({ includes, excludes }) {\n return {\n includes: includes && includes.map(m => m.pattern),\n excludes: excludes && excludes.map(m => m.pattern)\n };\n}\n\n/**\n * The class to test given paths are matched by the patterns.\n */\nclass OverrideTester {\n\n /**\n * Create a tester with given criteria.\n * If there are no criteria, returns `null`.\n * @param {string|string[]} files The glob patterns for included files.\n * @param {string|string[]} excludedFiles The glob patterns for excluded files.\n * @param {string} basePath The path to the base directory to test paths.\n * @returns {OverrideTester|null} The created instance or `null`.\n */\n static create(files, excludedFiles, basePath) {\n const includePatterns = normalizePatterns(files);\n const excludePatterns = normalizePatterns(excludedFiles);\n let endsWithWildcard = false;\n\n if (includePatterns.length === 0) {\n return null;\n }\n\n // Rejects absolute paths or relative paths to parents.\n for (const pattern of includePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n if (pattern.endsWith(\"*\")) {\n endsWithWildcard = true;\n }\n }\n for (const pattern of excludePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n }\n\n const includes = toMatcher(includePatterns);\n const excludes = toMatcher(excludePatterns);\n\n return new OverrideTester(\n [{ includes, excludes }],\n basePath,\n endsWithWildcard\n );\n }\n\n /**\n * Combine two testers by logical and.\n * If either of the testers was `null`, returns the other tester.\n * The `basePath` property of the two must be the same value.\n * @param {OverrideTester|null} a A tester.\n * @param {OverrideTester|null} b Another tester.\n * @returns {OverrideTester|null} Combined tester.\n */\n static and(a, b) {\n if (!b) {\n return a && new OverrideTester(\n a.patterns,\n a.basePath,\n a.endsWithWildcard\n );\n }\n if (!a) {\n return new OverrideTester(\n b.patterns,\n b.basePath,\n b.endsWithWildcard\n );\n }\n\n assert.strictEqual(a.basePath, b.basePath);\n return new OverrideTester(\n a.patterns.concat(b.patterns),\n a.basePath,\n a.endsWithWildcard || b.endsWithWildcard\n );\n }\n\n /**\n * Initialize this instance.\n * @param {Pattern[]} patterns The matchers.\n * @param {string} basePath The base path.\n * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.\n */\n constructor(patterns, basePath, endsWithWildcard = false) {\n\n /** @type {Pattern[]} */\n this.patterns = patterns;\n\n /** @type {string} */\n this.basePath = basePath;\n\n /** @type {boolean} */\n this.endsWithWildcard = endsWithWildcard;\n }\n\n /**\n * Test if a given path is matched or not.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the path was matched.\n */\n test(filePath) {\n if (typeof filePath !== \"string\" || !path.isAbsolute(filePath)) {\n throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);\n }\n const relativePath = path.relative(this.basePath, filePath);\n\n return this.patterns.every(({ includes, excludes }) => (\n (!includes || includes.some(m => m.match(relativePath))) &&\n (!excludes || !excludes.some(m => m.match(relativePath)))\n ));\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n if (this.patterns.length === 1) {\n return {\n ...patternToJson(this.patterns[0]),\n basePath: this.basePath\n };\n }\n return {\n AND: this.patterns.map(patternToJson),\n basePath: this.basePath\n };\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n return this.toJSON();\n }\n}\n\nexport { OverrideTester };\n","/**\n * @fileoverview `ConfigArray` class.\n * @author Toru Nagashima \n */\n\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array.js\";\nimport { ConfigDependency } from \"./config-dependency.js\";\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\nimport { OverrideTester } from \"./override-tester.js\";\n\nexport {\n ConfigArray,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview Config file operations. This file must be usable in the browser,\n * so no Node-specific code can be here.\n * @author Nicholas C. Zakas\n */\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\nconst RULE_SEVERITY_STRINGS = [\"off\", \"warn\", \"error\"],\n RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {\n map[value] = index;\n return map;\n }, {}),\n VALID_SEVERITIES = [0, 1, 2, \"off\", \"warn\", \"error\"];\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Normalizes the severity value of a rule's configuration to a number\n * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally\n * received from the user. A valid config value is either 0, 1, 2, the string \"off\" (treated the same as 0),\n * the string \"warn\" (treated the same as 1), the string \"error\" (treated the same as 2), or an array\n * whose first element is one of the above values. Strings are matched case-insensitively.\n * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.\n */\nfunction getRuleSeverity(ruleConfig) {\n const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (severityValue === 0 || severityValue === 1 || severityValue === 2) {\n return severityValue;\n }\n\n if (typeof severityValue === \"string\") {\n return RULE_SEVERITY[severityValue.toLowerCase()] || 0;\n }\n\n return 0;\n}\n\n/**\n * Converts old-style severity settings (0, 1, 2) into new-style\n * severity settings (off, warn, error) for all rules. Assumption is that severity\n * values have already been validated as correct.\n * @param {Object} config The config object to normalize.\n * @returns {void}\n */\nfunction normalizeToStrings(config) {\n\n if (config.rules) {\n Object.keys(config.rules).forEach(ruleId => {\n const ruleConfig = config.rules[ruleId];\n\n if (typeof ruleConfig === \"number\") {\n config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];\n } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === \"number\") {\n ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];\n }\n });\n }\n}\n\n/**\n * Determines if the severity for the given rule configuration represents an error.\n * @param {int|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} True if the rule represents an error, false if not.\n */\nfunction isErrorSeverity(ruleConfig) {\n return getRuleSeverity(ruleConfig) === 2;\n}\n\n/**\n * Checks whether a given config has valid severity or not.\n * @param {number|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isValidSeverity(ruleConfig) {\n let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (typeof severity === \"string\") {\n severity = severity.toLowerCase();\n }\n return VALID_SEVERITIES.indexOf(severity) !== -1;\n}\n\n/**\n * Checks whether every rule of a given config has valid severity or not.\n * @param {Object} config The configuration for rules.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isEverySeverityValid(config) {\n return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));\n}\n\n/**\n * Normalizes a value for a global in a config\n * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in\n * a global directive comment\n * @returns {(\"readable\"|\"writeable\"|\"off\")} The value normalized as a string\n * @throws Error if global value is invalid\n */\nfunction normalizeConfigGlobal(configuredValue) {\n switch (configuredValue) {\n case \"off\":\n return \"off\";\n\n case true:\n case \"true\":\n case \"writeable\":\n case \"writable\":\n return \"writable\";\n\n case null:\n case false:\n case \"false\":\n case \"readable\":\n case \"readonly\":\n return \"readonly\";\n\n default:\n throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);\n }\n}\n\nexport {\n getRuleSeverity,\n normalizeToStrings,\n isErrorSeverity,\n isValidSeverity,\n isEverySeverityValid,\n normalizeConfigGlobal\n};\n","/**\n * @fileoverview Provide the function that emits deprecation warnings.\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport path from \"path\";\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\n// Defitions for deprecation warnings.\nconst deprecationWarningMessages = {\n ESLINT_LEGACY_ECMAFEATURES:\n \"The 'ecmaFeatures' config file property is deprecated and has no effect.\",\n ESLINT_PERSONAL_CONFIG_LOAD:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please use a config file per project or the '--config' option.\",\n ESLINT_PERSONAL_CONFIG_SUPPRESS:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please remove it or add 'root:true' to the config files in your \" +\n \"projects in order to avoid loading '~/.eslintrc.*' accidentally.\"\n};\n\nconst sourceFileErrorCache = new Set();\n\n/**\n * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted\n * for each unique file path, but repeated invocations with the same file path have no effect.\n * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.\n * @param {string} source The name of the configuration source to report the warning for.\n * @param {string} errorCode The warning message to show.\n * @returns {void}\n */\nfunction emitDeprecationWarning(source, errorCode) {\n const cacheKey = JSON.stringify({ source, errorCode });\n\n if (sourceFileErrorCache.has(cacheKey)) {\n return;\n }\n sourceFileErrorCache.add(cacheKey);\n\n const rel = path.relative(process.cwd(), source);\n const message = deprecationWarningMessages[errorCode];\n\n process.emitWarning(\n `${message} (found in \"${rel}\")`,\n \"DeprecationWarning\",\n errorCode\n );\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n emitDeprecationWarning\n};\n","/**\n * @fileoverview The instance of Ajv validator.\n * @author Evgeny Poberezkin\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport Ajv from \"ajv\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/*\n * Copied from ajv/lib/refs/json-schema-draft-04.json\n * The MIT License (MIT)\n * Copyright (c) 2015-2017 Evgeny Poberezkin\n */\nconst metaSchema = {\n id: \"http://json-schema.org/draft-04/schema#\",\n $schema: \"http://json-schema.org/draft-04/schema#\",\n description: \"Core schema meta-schema\",\n definitions: {\n schemaArray: {\n type: \"array\",\n minItems: 1,\n items: { $ref: \"#\" }\n },\n positiveInteger: {\n type: \"integer\",\n minimum: 0\n },\n positiveIntegerDefault0: {\n allOf: [{ $ref: \"#/definitions/positiveInteger\" }, { default: 0 }]\n },\n simpleTypes: {\n enum: [\"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\"]\n },\n stringArray: {\n type: \"array\",\n items: { type: \"string\" },\n minItems: 1,\n uniqueItems: true\n }\n },\n type: \"object\",\n properties: {\n id: {\n type: \"string\"\n },\n $schema: {\n type: \"string\"\n },\n title: {\n type: \"string\"\n },\n description: {\n type: \"string\"\n },\n default: { },\n multipleOf: {\n type: \"number\",\n minimum: 0,\n exclusiveMinimum: true\n },\n maximum: {\n type: \"number\"\n },\n exclusiveMaximum: {\n type: \"boolean\",\n default: false\n },\n minimum: {\n type: \"number\"\n },\n exclusiveMinimum: {\n type: \"boolean\",\n default: false\n },\n maxLength: { $ref: \"#/definitions/positiveInteger\" },\n minLength: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n pattern: {\n type: \"string\",\n format: \"regex\"\n },\n additionalItems: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n items: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/schemaArray\" }\n ],\n default: { }\n },\n maxItems: { $ref: \"#/definitions/positiveInteger\" },\n minItems: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n uniqueItems: {\n type: \"boolean\",\n default: false\n },\n maxProperties: { $ref: \"#/definitions/positiveInteger\" },\n minProperties: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n required: { $ref: \"#/definitions/stringArray\" },\n additionalProperties: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n definitions: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n properties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n patternProperties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n dependencies: {\n type: \"object\",\n additionalProperties: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/stringArray\" }\n ]\n }\n },\n enum: {\n type: \"array\",\n minItems: 1,\n uniqueItems: true\n },\n type: {\n anyOf: [\n { $ref: \"#/definitions/simpleTypes\" },\n {\n type: \"array\",\n items: { $ref: \"#/definitions/simpleTypes\" },\n minItems: 1,\n uniqueItems: true\n }\n ]\n },\n format: { type: \"string\" },\n allOf: { $ref: \"#/definitions/schemaArray\" },\n anyOf: { $ref: \"#/definitions/schemaArray\" },\n oneOf: { $ref: \"#/definitions/schemaArray\" },\n not: { $ref: \"#\" }\n },\n dependencies: {\n exclusiveMaximum: [\"maximum\"],\n exclusiveMinimum: [\"minimum\"]\n },\n default: { }\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport default (additionalOptions = {}) => {\n const ajv = new Ajv({\n meta: false,\n useDefaults: true,\n validateSchema: false,\n missingRefs: \"ignore\",\n verbose: true,\n schemaId: \"auto\",\n ...additionalOptions\n });\n\n ajv.addMetaSchema(metaSchema);\n // eslint-disable-next-line no-underscore-dangle\n ajv._opts.defaultMeta = metaSchema.id;\n\n return ajv;\n};\n","/**\n * @fileoverview Defines a schema for configs.\n * @author Sylvan Mably\n */\n\nconst baseConfigProperties = {\n $schema: { type: \"string\" },\n env: { type: \"object\" },\n extends: { $ref: \"#/definitions/stringOrStrings\" },\n globals: { type: \"object\" },\n overrides: {\n type: \"array\",\n items: { $ref: \"#/definitions/overrideConfig\" },\n additionalItems: false\n },\n parser: { type: [\"string\", \"null\"] },\n parserOptions: { type: \"object\" },\n plugins: { type: \"array\" },\n processor: { type: \"string\" },\n rules: { type: \"object\" },\n settings: { type: \"object\" },\n noInlineConfig: { type: \"boolean\" },\n reportUnusedDisableDirectives: { type: \"boolean\" },\n\n ecmaFeatures: { type: \"object\" } // deprecated; logs a warning when used\n};\n\nconst configSchema = {\n definitions: {\n stringOrStrings: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false\n }\n ]\n },\n stringOrStringsRequired: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false,\n minItems: 1\n }\n ]\n },\n\n // Config at top-level.\n objectConfig: {\n type: \"object\",\n properties: {\n root: { type: \"boolean\" },\n ignorePatterns: { $ref: \"#/definitions/stringOrStrings\" },\n ...baseConfigProperties\n },\n additionalProperties: false\n },\n\n // Config in `overrides`.\n overrideConfig: {\n type: \"object\",\n properties: {\n excludedFiles: { $ref: \"#/definitions/stringOrStrings\" },\n files: { $ref: \"#/definitions/stringOrStringsRequired\" },\n ...baseConfigProperties\n },\n required: [\"files\"],\n additionalProperties: false\n }\n },\n\n $ref: \"#/definitions/objectConfig\"\n};\n\nexport default configSchema;\n","/**\n * @fileoverview Defines environment settings and globals.\n * @author Elan Shanker\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport globals from \"globals\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the object that has difference.\n * @param {Record} current The newer object.\n * @param {Record} prev The older object.\n * @returns {Record} The difference object.\n */\nfunction getDiff(current, prev) {\n const retv = {};\n\n for (const [key, value] of Object.entries(current)) {\n if (!Object.hasOwnProperty.call(prev, key)) {\n retv[key] = value;\n }\n }\n\n return retv;\n}\n\nconst newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...\nconst newGlobals2017 = {\n Atomics: false,\n SharedArrayBuffer: false\n};\nconst newGlobals2020 = {\n BigInt: false,\n BigInt64Array: false,\n BigUint64Array: false,\n globalThis: false\n};\n\nconst newGlobals2021 = {\n AggregateError: false,\n FinalizationRegistry: false,\n WeakRef: false\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/** @type {Map} */\nexport default new Map(Object.entries({\n\n // Language\n builtin: {\n globals: globals.es5\n },\n es6: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2015: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2016: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 7\n }\n },\n es2017: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 8\n }\n },\n es2018: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 9\n }\n },\n es2019: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 10\n }\n },\n es2020: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },\n parserOptions: {\n ecmaVersion: 11\n }\n },\n es2021: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 12\n }\n },\n es2022: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 13\n }\n },\n\n // Platforms\n browser: {\n globals: globals.browser\n },\n node: {\n globals: globals.node,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n \"shared-node-browser\": {\n globals: globals[\"shared-node-browser\"]\n },\n worker: {\n globals: globals.worker\n },\n serviceworker: {\n globals: globals.serviceworker\n },\n\n // Frameworks\n commonjs: {\n globals: globals.commonjs,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n amd: {\n globals: globals.amd\n },\n mocha: {\n globals: globals.mocha\n },\n jasmine: {\n globals: globals.jasmine\n },\n jest: {\n globals: globals.jest\n },\n phantomjs: {\n globals: globals.phantomjs\n },\n jquery: {\n globals: globals.jquery\n },\n qunit: {\n globals: globals.qunit\n },\n prototypejs: {\n globals: globals.prototypejs\n },\n shelljs: {\n globals: globals.shelljs\n },\n meteor: {\n globals: globals.meteor\n },\n mongo: {\n globals: globals.mongo\n },\n protractor: {\n globals: globals.protractor\n },\n applescript: {\n globals: globals.applescript\n },\n nashorn: {\n globals: globals.nashorn\n },\n atomtest: {\n globals: globals.atomtest\n },\n embertest: {\n globals: globals.embertest\n },\n webextensions: {\n globals: globals.webextensions\n },\n greasemonkey: {\n globals: globals.greasemonkey\n }\n}));\n","/**\n * @fileoverview Validates configs.\n * @author Brandon Mills\n */\n\n/* eslint class-methods-use-this: \"off\" */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport util from \"util\";\nimport * as ConfigOps from \"./config-ops.js\";\nimport { emitDeprecationWarning } from \"./deprecation-warnings.js\";\nimport ajvOrig from \"./ajv.js\";\nimport configSchema from \"../../conf/config-schema.js\";\nimport BuiltInEnvironments from \"../../conf/environments.js\";\n\nconst ajv = ajvOrig();\n\nconst ruleValidators = new WeakMap();\nconst noop = Function.prototype;\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\nlet validateSchema;\nconst severityMap = {\n error: 2,\n warn: 1,\n off: 0\n};\n\nconst validated = new WeakSet();\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nexport default class ConfigValidator {\n constructor({ builtInRules = new Map() } = {}) {\n this.builtInRules = builtInRules;\n }\n\n /**\n * Gets a complete options schema for a rule.\n * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object\n * @returns {Object} JSON Schema for the rule's options.\n */\n getRuleOptionsSchema(rule) {\n if (!rule) {\n return null;\n }\n\n const schema = rule.schema || rule.meta && rule.meta.schema;\n\n // Given a tuple of schemas, insert warning level at the beginning\n if (Array.isArray(schema)) {\n if (schema.length) {\n return {\n type: \"array\",\n items: schema,\n minItems: 0,\n maxItems: schema.length\n };\n }\n return {\n type: \"array\",\n minItems: 0,\n maxItems: 0\n };\n\n }\n\n // Given a full schema, leave it alone\n return schema || null;\n }\n\n /**\n * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.\n * @param {options} options The given options for the rule.\n * @returns {number|string} The rule's severity value\n */\n validateRuleSeverity(options) {\n const severity = Array.isArray(options) ? options[0] : options;\n const normSeverity = typeof severity === \"string\" ? severityMap[severity.toLowerCase()] : severity;\n\n if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {\n return normSeverity;\n }\n\n throw new Error(`\\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, \"\\\"\").replace(/\\n/gu, \"\")}').\\n`);\n\n }\n\n /**\n * Validates the non-severity options passed to a rule, based on its schema.\n * @param {{create: Function}} rule The rule to validate\n * @param {Array} localOptions The options for the rule, excluding severity\n * @returns {void}\n */\n validateRuleSchema(rule, localOptions) {\n if (!ruleValidators.has(rule)) {\n const schema = this.getRuleOptionsSchema(rule);\n\n if (schema) {\n ruleValidators.set(rule, ajv.compile(schema));\n }\n }\n\n const validateRule = ruleValidators.get(rule);\n\n if (validateRule) {\n validateRule(localOptions);\n if (validateRule.errors) {\n throw new Error(validateRule.errors.map(\n error => `\\tValue ${JSON.stringify(error.data)} ${error.message}.\\n`\n ).join(\"\"));\n }\n }\n }\n\n /**\n * Validates a rule's options against its schema.\n * @param {{create: Function}|null} rule The rule that the config is being validated for\n * @param {string} ruleId The rule's unique name.\n * @param {Array|number} options The given options for the rule.\n * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,\n * no source is prepended to the message.\n * @returns {void}\n */\n validateRuleOptions(rule, ruleId, options, source = null) {\n try {\n const severity = this.validateRuleSeverity(options);\n\n if (severity !== 0) {\n this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);\n }\n } catch (err) {\n const enhancedMessage = `Configuration for rule \"${ruleId}\" is invalid:\\n${err.message}`;\n\n if (typeof source === \"string\") {\n throw new Error(`${source}:\\n\\t${enhancedMessage}`);\n } else {\n throw new Error(enhancedMessage);\n }\n }\n }\n\n /**\n * Validates an environment object\n * @param {Object} environment The environment config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.\n * @returns {void}\n */\n validateEnvironment(\n environment,\n source,\n getAdditionalEnv = noop\n ) {\n\n // not having an environment is ok\n if (!environment) {\n return;\n }\n\n Object.keys(environment).forEach(id => {\n const env = getAdditionalEnv(id) || BuiltInEnvironments.get(id) || null;\n\n if (!env) {\n const message = `${source}:\\n\\tEnvironment key \"${id}\" is unknown\\n`;\n\n throw new Error(message);\n }\n });\n }\n\n /**\n * Validates a rules config object\n * @param {Object} rulesConfig The rules config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules\n * @returns {void}\n */\n validateRules(\n rulesConfig,\n source,\n getAdditionalRule = noop\n ) {\n if (!rulesConfig) {\n return;\n }\n\n Object.keys(rulesConfig).forEach(id => {\n const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;\n\n this.validateRuleOptions(rule, id, rulesConfig[id], source);\n });\n }\n\n /**\n * Validates a `globals` section of a config file\n * @param {Object} globalsConfig The `globals` section\n * @param {string|null} source The name of the configuration source to report in the event of an error.\n * @returns {void}\n */\n validateGlobals(globalsConfig, source = null) {\n if (!globalsConfig) {\n return;\n }\n\n Object.entries(globalsConfig)\n .forEach(([configuredGlobal, configuredValue]) => {\n try {\n ConfigOps.normalizeConfigGlobal(configuredValue);\n } catch (err) {\n throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\\n${err.message}`);\n }\n });\n }\n\n /**\n * Validate `processor` configuration.\n * @param {string|undefined} processorName The processor name.\n * @param {string} source The name of config file.\n * @param {function(id:string): Processor} getProcessor The getter of defined processors.\n * @returns {void}\n */\n validateProcessor(processorName, source, getProcessor) {\n if (processorName && !getProcessor(processorName)) {\n throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);\n }\n }\n\n /**\n * Formats an array of schema validation errors.\n * @param {Array} errors An array of error messages to format.\n * @returns {string} Formatted error message\n */\n formatErrors(errors) {\n return errors.map(error => {\n if (error.keyword === \"additionalProperties\") {\n const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;\n\n return `Unexpected top-level property \"${formattedPropertyPath}\"`;\n }\n if (error.keyword === \"type\") {\n const formattedField = error.dataPath.slice(1);\n const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join(\"/\") : error.schema;\n const formattedValue = JSON.stringify(error.data);\n\n return `Property \"${formattedField}\" is the wrong type (expected ${formattedExpectedType} but got \\`${formattedValue}\\`)`;\n }\n\n const field = error.dataPath[0] === \".\" ? error.dataPath.slice(1) : error.dataPath;\n\n return `\"${field}\" ${error.message}. Value: ${JSON.stringify(error.data)}`;\n }).map(message => `\\t- ${message}.\\n`).join(\"\");\n }\n\n /**\n * Validates the top level properties of the config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @returns {void}\n */\n validateConfigSchema(config, source = null) {\n validateSchema = validateSchema || ajv.compile(configSchema);\n\n if (!validateSchema(config)) {\n throw new Error(`ESLint configuration in ${source} is invalid:\\n${this.formatErrors(validateSchema.errors)}`);\n }\n\n if (Object.hasOwnProperty.call(config, \"ecmaFeatures\")) {\n emitDeprecationWarning(source, \"ESLINT_LEGACY_ECMAFEATURES\");\n }\n }\n\n /**\n * Validates an entire config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.\n * @returns {void}\n */\n validate(config, source, getAdditionalRule, getAdditionalEnv) {\n this.validateConfigSchema(config, source);\n this.validateRules(config.rules, source, getAdditionalRule);\n this.validateEnvironment(config.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n\n for (const override of config.overrides || []) {\n this.validateRules(override.rules, source, getAdditionalRule);\n this.validateEnvironment(override.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n }\n }\n\n /**\n * Validate config array object.\n * @param {ConfigArray} configArray The config array to validate.\n * @returns {void}\n */\n validateConfigArray(configArray) {\n const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);\n const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);\n const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);\n\n // Validate.\n for (const element of configArray) {\n if (validated.has(element)) {\n continue;\n }\n validated.add(element);\n\n this.validateEnvironment(element.env, element.name, getPluginEnv);\n this.validateGlobals(element.globals, element.name);\n this.validateProcessor(element.processor, element.name, getPluginProcessor);\n this.validateRules(element.rules, element.name, getPluginRule);\n }\n }\n\n}\n","/**\n * @fileoverview Common helpers for naming of plugins, formatters and configs\n */\n\nconst NAMESPACE_REGEX = /^@.*\\//iu;\n\n/**\n * Brings package name to correct format based on prefix\n * @param {string} name The name of the package.\n * @param {string} prefix Can be either \"eslint-plugin\", \"eslint-config\" or \"eslint-formatter\"\n * @returns {string} Normalized name of the package\n * @private\n */\nfunction normalizePackageName(name, prefix) {\n let normalizedName = name;\n\n /**\n * On Windows, name can come in with Windows slashes instead of Unix slashes.\n * Normalize to Unix first to avoid errors later on.\n * https://github.com/eslint/eslint/issues/5644\n */\n if (normalizedName.includes(\"\\\\\")) {\n normalizedName = normalizedName.replace(/\\\\/gu, \"/\");\n }\n\n if (normalizedName.charAt(0) === \"@\") {\n\n /**\n * it's a scoped package\n * package name is the prefix, or just a username\n */\n const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, \"u\"),\n scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, \"u\");\n\n if (scopedPackageShortcutRegex.test(normalizedName)) {\n normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);\n } else if (!scopedPackageNameRegex.test(normalizedName.split(\"/\")[1])) {\n\n /**\n * for scoped packages, insert the prefix after the first / unless\n * the path is already @scope/eslint or @scope/eslint-xxx-yyy\n */\n normalizedName = normalizedName.replace(/^@([^/]+)\\/(.*)$/u, `@$1/${prefix}-$2`);\n }\n } else if (!normalizedName.startsWith(`${prefix}-`)) {\n normalizedName = `${prefix}-${normalizedName}`;\n }\n\n return normalizedName;\n}\n\n/**\n * Removes the prefix from a fullname.\n * @param {string} fullname The term which may have the prefix.\n * @param {string} prefix The prefix to remove.\n * @returns {string} The term without prefix.\n */\nfunction getShorthandName(fullname, prefix) {\n if (fullname[0] === \"@\") {\n let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, \"u\").exec(fullname);\n\n if (matchResult) {\n return matchResult[1];\n }\n\n matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, \"u\").exec(fullname);\n if (matchResult) {\n return `${matchResult[1]}/${matchResult[2]}`;\n }\n } else if (fullname.startsWith(`${prefix}-`)) {\n return fullname.slice(prefix.length + 1);\n }\n\n return fullname;\n}\n\n/**\n * Gets the scope (namespace) of a term.\n * @param {string} term The term which may have the namespace.\n * @returns {string} The namespace of the term if it has one.\n */\nfunction getNamespaceFromTerm(term) {\n const match = term.match(NAMESPACE_REGEX);\n\n return match ? match[0] : \"\";\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n normalizePackageName,\n getShorthandName,\n getNamespaceFromTerm\n};\n","/**\n * Utility for resolving a module relative to another module\n * @author Teddy Katz\n */\n\nimport Module from \"module\";\n\n/*\n * `Module.createRequire` is added in v12.2.0. It supports URL as well.\n * We only support the case where the argument is a filepath, not a URL.\n */\nconst createRequire = Module.createRequire;\n\n/**\n * Resolves a Node module relative to another module\n * @param {string} moduleName The name of a Node module, or a path to a Node module.\n * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be\n * a file rather than a directory, but the file need not actually exist.\n * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`\n */\nfunction resolve(moduleName, relativeToPath) {\n try {\n return createRequire(relativeToPath).resolve(moduleName);\n } catch (error) {\n\n // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.\n if (\n typeof error === \"object\" &&\n error !== null &&\n error.code === \"MODULE_NOT_FOUND\" &&\n !error.requireStack &&\n error.message.includes(moduleName)\n ) {\n error.message += `\\nRequire stack:\\n- ${relativeToPath}`;\n }\n throw error;\n }\n}\n\nexport {\n resolve\n};\n","/**\n * @fileoverview The factory of `ConfigArray` objects.\n *\n * This class provides methods to create `ConfigArray` instance.\n *\n * - `create(configData, options)`\n * Create a `ConfigArray` instance from a config data. This is to handle CLI\n * options except `--config`.\n * - `loadFile(filePath, options)`\n * Create a `ConfigArray` instance from a config file. This is to handle\n * `--config` option. If the file was not found, throws the following error:\n * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.\n * - If the filename was `package.json`, an IO error or an\n * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.\n * - Otherwise, an IO error such as `ENOENT`.\n * - `loadInDirectory(directoryPath, options)`\n * Create a `ConfigArray` instance from a config file which is on a given\n * directory. This tries to load `.eslintrc.*` or `package.json`. If not\n * found, returns an empty `ConfigArray`.\n * - `loadESLintIgnore(filePath)`\n * Create a `ConfigArray` instance from a config file that is `.eslintignore`\n * format. This is to handle `--ignore-path` option.\n * - `loadDefaultESLintIgnore()`\n * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in\n * the current working directory.\n *\n * `ConfigArrayFactory` class has the responsibility that loads configuration\n * files, including loading `extends`, `parser`, and `plugins`. The created\n * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.\n *\n * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class\n * handles cascading and hierarchy.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport fs from \"fs\";\nimport importFresh from \"import-fresh\";\nimport { createRequire } from \"module\";\nimport path from \"path\";\nimport stripComments from \"strip-json-comments\";\n\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern,\n OverrideTester\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\n\nconst require = createRequire(import.meta.url);\n\nconst debug = debugOrig(\"eslintrc:config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\nconst configFilenames = [\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \".eslintrc.json\",\n \".eslintrc\",\n \"package.json\"\n];\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").OverrideConfigData} OverrideConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {import(\"./config-array/config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-array/config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {ConfigArray[0]} ConfigArrayElement */\n\n/**\n * @typedef {Object} ConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {string} [cwd] The path to the current working directory.\n * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryInternalSlots\n * @property {Map} additionalPluginPool The map for additional plugins.\n * @property {string} cwd The path to the current working directory.\n * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {string} pluginBasePath The base path to resolve plugins.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Check if a given string is a file path.\n * @param {string} nameOrPath A module name or file path.\n * @returns {boolean} `true` if the `nameOrPath` is a file path.\n */\nfunction isFilePath(nameOrPath) {\n return (\n /^\\.{1,2}[/\\\\]/u.test(nameOrPath) ||\n path.isAbsolute(nameOrPath)\n );\n}\n\n/**\n * Convenience wrapper for synchronously reading file contents.\n * @param {string} filePath The filename to read.\n * @returns {string} The file contents, with the BOM removed.\n * @private\n */\nfunction readFile(filePath) {\n return fs.readFileSync(filePath, \"utf8\").replace(/^\\ufeff/u, \"\");\n}\n\n/**\n * Loads a YAML configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadYAMLConfigFile(filePath) {\n debug(`Loading YAML config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n\n // empty YAML file can be null, so always use\n return yaml.load(readFile(filePath)) || {};\n } catch (e) {\n debug(`Error reading YAML file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JSON configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSONConfigFile(filePath) {\n debug(`Loading JSON config file: ${filePath}`);\n\n try {\n return JSON.parse(stripComments(readFile(filePath)));\n } catch (e) {\n debug(`Error reading JSON file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n e.messageTemplate = \"failed-to-read-json\";\n e.messageData = {\n path: filePath,\n message: e.message\n };\n throw e;\n }\n}\n\n/**\n * Loads a legacy (.eslintrc) configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadLegacyConfigFile(filePath) {\n debug(`Loading legacy config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n return yaml.load(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};\n } catch (e) {\n debug(\"Error reading YAML file: %s\\n%o\", filePath, e);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JavaScript configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSConfigFile(filePath) {\n debug(`Loading JS config file: ${filePath}`);\n try {\n return importFresh(filePath);\n } catch (e) {\n debug(`Error reading JavaScript file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a configuration from a package.json file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadPackageJSONConfigFile(filePath) {\n debug(`Loading package.json config file: ${filePath}`);\n try {\n const packageData = loadJSONConfigFile(filePath);\n\n if (!Object.hasOwnProperty.call(packageData, \"eslintConfig\")) {\n throw Object.assign(\n new Error(\"package.json file doesn't have 'eslintConfig' field.\"),\n { code: \"ESLINT_CONFIG_FIELD_NOT_FOUND\" }\n );\n }\n\n return packageData.eslintConfig;\n } catch (e) {\n debug(`Error reading package.json file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a `.eslintignore` from a file.\n * @param {string} filePath The filename to load.\n * @returns {string[]} The ignore patterns from the file.\n * @private\n */\nfunction loadESLintIgnoreFile(filePath) {\n debug(`Loading .eslintignore file: ${filePath}`);\n\n try {\n return readFile(filePath)\n .split(/\\r?\\n/gu)\n .filter(line => line.trim() !== \"\" && !line.startsWith(\"#\"));\n } catch (e) {\n debug(`Error reading .eslintignore file: ${filePath}`);\n e.message = `Cannot read .eslintignore file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Creates an error to notify about a missing config to extend from.\n * @param {string} configName The name of the missing config.\n * @param {string} importerName The name of the config that imported the missing config\n * @param {string} messageTemplate The text template to source error strings from.\n * @returns {Error} The error object to throw\n * @private\n */\nfunction configInvalidError(configName, importerName, messageTemplate) {\n return Object.assign(\n new Error(`Failed to load config \"${configName}\" to extend from.`),\n {\n messageTemplate,\n messageData: { configName, importerName }\n }\n );\n}\n\n/**\n * Loads a configuration file regardless of the source. Inspects the file path\n * to determine the correctly way to load the config file.\n * @param {string} filePath The path to the configuration.\n * @returns {ConfigData|null} The configuration information.\n * @private\n */\nfunction loadConfigFile(filePath) {\n switch (path.extname(filePath)) {\n case \".js\":\n case \".cjs\":\n return loadJSConfigFile(filePath);\n\n case \".json\":\n if (path.basename(filePath) === \"package.json\") {\n return loadPackageJSONConfigFile(filePath);\n }\n return loadJSONConfigFile(filePath);\n\n case \".yaml\":\n case \".yml\":\n return loadYAMLConfigFile(filePath);\n\n default:\n return loadLegacyConfigFile(filePath);\n }\n}\n\n/**\n * Write debug log.\n * @param {string} request The requested module name.\n * @param {string} relativeTo The file path to resolve the request relative to.\n * @param {string} filePath The resolved file path.\n * @returns {void}\n */\nfunction writeDebugLogForLoading(request, relativeTo, filePath) {\n /* istanbul ignore next */\n if (debug.enabled) {\n let nameAndVersion = null;\n\n try {\n const packageJsonPath = ModuleResolver.resolve(\n `${request}/package.json`,\n relativeTo\n );\n const { version = \"unknown\" } = require(packageJsonPath);\n\n nameAndVersion = `${request}@${version}`;\n } catch (error) {\n debug(\"package.json was not found:\", error.message);\n nameAndVersion = request;\n }\n\n debug(\"Loaded: %s (%s)\", nameAndVersion, filePath);\n }\n}\n\n/**\n * Create a new context with default values.\n * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.\n * @param {\"config\" | \"ignore\" | \"implicit-processor\" | undefined} providedType The type of the current configuration. Default is `\"config\"`.\n * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.\n * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.\n * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.\n * @returns {ConfigArrayFactoryLoadingContext} The created context.\n */\nfunction createContext(\n { cwd, resolvePluginsRelativeTo },\n providedType,\n providedName,\n providedFilePath,\n providedMatchBasePath\n) {\n const filePath = providedFilePath\n ? path.resolve(cwd, providedFilePath)\n : \"\";\n const matchBasePath =\n (providedMatchBasePath && path.resolve(cwd, providedMatchBasePath)) ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const name =\n providedName ||\n (filePath && path.relative(cwd, filePath)) ||\n \"\";\n const pluginBasePath =\n resolvePluginsRelativeTo ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const type = providedType || \"config\";\n\n return { filePath, matchBasePath, name, pluginBasePath, type };\n}\n\n/**\n * Normalize a given plugin.\n * - Ensure the object to have four properties: configs, environments, processors, and rules.\n * - Ensure the object to not have other properties.\n * @param {Plugin} plugin The plugin to normalize.\n * @returns {Plugin} The normalized plugin.\n */\nfunction normalizePlugin(plugin) {\n return {\n configs: plugin.configs || {},\n environments: plugin.environments || {},\n processors: plugin.processors || {},\n rules: plugin.rules || {}\n };\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The factory of `ConfigArray` objects.\n */\nclass ConfigArrayFactory {\n\n /**\n * Initialize this instance.\n * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.\n */\n constructor({\n additionalPluginPool = new Map(),\n cwd = process.cwd(),\n resolvePluginsRelativeTo,\n builtInRules,\n resolver = ModuleResolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = {}) {\n internalSlotsMap.set(this, {\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo:\n resolvePluginsRelativeTo &&\n path.resolve(cwd, resolvePluginsRelativeTo),\n builtInRules,\n resolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n });\n }\n\n /**\n * Create `ConfigArray` instance from a config data.\n * @param {ConfigData|null} configData The config data to create.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.filePath] The path to this config data.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n create(configData, { basePath, filePath, name } = {}) {\n if (!configData) {\n return new ConfigArray();\n }\n\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n const elements = this._normalizeConfigData(configData, ctx);\n\n return new ConfigArray(...elements);\n }\n\n /**\n * Load a config file.\n * @param {string} filePath The path to a config file.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n loadFile(filePath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n\n return new ConfigArray(...this._loadConfigData(ctx));\n }\n\n /**\n * Load the config file on a given directory if exists.\n * @param {string} directoryPath The path to a directory.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadInDirectory(directoryPath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n\n for (const filename of configFilenames) {\n const ctx = createContext(\n slots,\n \"config\",\n name,\n path.join(directoryPath, filename),\n basePath\n );\n\n if (fs.existsSync(ctx.filePath) && fs.statSync(ctx.filePath).isFile()) {\n let configData;\n\n try {\n configData = loadConfigFile(ctx.filePath);\n } catch (error) {\n if (!error || error.code !== \"ESLINT_CONFIG_FIELD_NOT_FOUND\") {\n throw error;\n }\n }\n\n if (configData) {\n debug(`Config file found: ${ctx.filePath}`);\n return new ConfigArray(\n ...this._normalizeConfigData(configData, ctx)\n );\n }\n }\n }\n\n debug(`Config file not found on ${directoryPath}`);\n return new ConfigArray();\n }\n\n /**\n * Check if a config file on a given directory exists or not.\n * @param {string} directoryPath The path to a directory.\n * @returns {string | null} The path to the found config file. If not found then null.\n */\n static getPathToConfigFileInDirectory(directoryPath) {\n for (const filename of configFilenames) {\n const filePath = path.join(directoryPath, filename);\n\n if (fs.existsSync(filePath)) {\n if (filename === \"package.json\") {\n try {\n loadPackageJSONConfigFile(filePath);\n return filePath;\n } catch { /* ignore */ }\n } else {\n return filePath;\n }\n }\n }\n return null;\n }\n\n /**\n * Load `.eslintignore` file.\n * @param {string} filePath The path to a `.eslintignore` file to load.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadESLintIgnore(filePath) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(\n slots,\n \"ignore\",\n void 0,\n filePath,\n slots.cwd\n );\n const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)\n );\n }\n\n /**\n * Load `.eslintignore` file in the current working directory.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadDefaultESLintIgnore() {\n const slots = internalSlotsMap.get(this);\n const eslintIgnorePath = path.resolve(slots.cwd, \".eslintignore\");\n const packageJsonPath = path.resolve(slots.cwd, \"package.json\");\n\n if (fs.existsSync(eslintIgnorePath)) {\n return this.loadESLintIgnore(eslintIgnorePath);\n }\n if (fs.existsSync(packageJsonPath)) {\n const data = loadJSONConfigFile(packageJsonPath);\n\n if (Object.hasOwnProperty.call(data, \"eslintIgnore\")) {\n if (!Array.isArray(data.eslintIgnore)) {\n throw new Error(\"Package.json eslintIgnore property requires an array of paths\");\n }\n const ctx = createContext(\n slots,\n \"ignore\",\n \"eslintIgnore in package.json\",\n packageJsonPath,\n slots.cwd\n );\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)\n );\n }\n }\n\n return new ConfigArray();\n }\n\n /**\n * Load a given config file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} Loaded config.\n * @private\n */\n _loadConfigData(ctx) {\n return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);\n }\n\n /**\n * Normalize a given `.eslintignore` data to config array elements.\n * @param {string[]} ignorePatterns The patterns to ignore files.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeESLintIgnoreData(ignorePatterns, ctx) {\n const elements = this._normalizeObjectConfigData(\n { ignorePatterns },\n ctx\n );\n\n // Set `ignorePattern.loose` flag for backward compatibility.\n for (const element of elements) {\n if (element.ignorePattern) {\n element.ignorePattern.loose = true;\n }\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _normalizeConfigData(configData, ctx) {\n const validator = new ConfigValidator();\n\n validator.validateConfigSchema(configData, ctx.name || ctx.filePath);\n return this._normalizeObjectConfigData(configData, ctx);\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData|OverrideConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigData(configData, ctx) {\n const { files, excludedFiles, ...configBody } = configData;\n const criteria = OverrideTester.create(\n files,\n excludedFiles,\n ctx.matchBasePath\n );\n const elements = this._normalizeObjectConfigDataBody(configBody, ctx);\n\n // Apply the criteria to every element.\n for (const element of elements) {\n\n /*\n * Merge the criteria.\n * This is for the `overrides` entries that came from the\n * configurations of `overrides[].extends`.\n */\n element.criteria = OverrideTester.and(criteria, element.criteria);\n\n /*\n * Remove `root` property to ignore `root` settings which came from\n * `extends` in `overrides`.\n */\n if (element.criteria) {\n element.root = void 0;\n }\n\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigDataBody(\n {\n env,\n extends: extend,\n globals,\n ignorePatterns,\n noInlineConfig,\n parser: parserName,\n parserOptions,\n plugins: pluginList,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings,\n overrides: overrideList = []\n },\n ctx\n ) {\n const extendList = Array.isArray(extend) ? extend : [extend];\n const ignorePattern = ignorePatterns && new IgnorePattern(\n Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],\n ctx.matchBasePath\n );\n\n // Flatten `extends`.\n for (const extendName of extendList.filter(Boolean)) {\n yield* this._loadExtends(extendName, ctx);\n }\n\n // Load parser & plugins.\n const parser = parserName && this._loadParser(parserName, ctx);\n const plugins = pluginList && this._loadPlugins(pluginList, ctx);\n\n // Yield pseudo config data for file extension processors.\n if (plugins) {\n yield* this._takeFileExtensionProcessors(plugins, ctx);\n }\n\n // Yield the config data except `extends` and `overrides`.\n yield {\n\n // Debug information.\n type: ctx.type,\n name: ctx.name,\n filePath: ctx.filePath,\n\n // Config data.\n criteria: null,\n env,\n globals,\n ignorePattern,\n noInlineConfig,\n parser,\n parserOptions,\n plugins,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings\n };\n\n // Flatten `overries`.\n for (let i = 0; i < overrideList.length; ++i) {\n yield* this._normalizeObjectConfigData(\n overrideList[i],\n { ...ctx, name: `${ctx.name}#overrides[${i}]` }\n );\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtends(extendName, ctx) {\n debug(\"Loading {extends:%j} relative to %s\", extendName, ctx.filePath);\n try {\n if (extendName.startsWith(\"eslint:\")) {\n return this._loadExtendedBuiltInConfig(extendName, ctx);\n }\n if (extendName.startsWith(\"plugin:\")) {\n return this._loadExtendedPluginConfig(extendName, ctx);\n }\n return this._loadExtendedShareableConfig(extendName, ctx);\n } catch (error) {\n error.message += `\\nReferenced from: ${ctx.filePath || ctx.name}`;\n throw error;\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedBuiltInConfig(extendName, ctx) {\n const {\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = internalSlotsMap.get(this);\n\n if (extendName === \"eslint:recommended\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintRecommendedConfig) {\n if (typeof getEslintRecommendedConfig !== \"function\") {\n throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);\n }\n return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintRecommendedPath\n });\n }\n if (extendName === \"eslint:all\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintAllConfig) {\n if (typeof getEslintAllConfig !== \"function\") {\n throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);\n }\n return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintAllPath\n });\n }\n\n throw configInvalidError(extendName, ctx.name, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedPluginConfig(extendName, ctx) {\n const slashIndex = extendName.lastIndexOf(\"/\");\n\n if (slashIndex === -1) {\n throw configInvalidError(extendName, ctx.filePath, \"plugin-invalid\");\n }\n\n const pluginName = extendName.slice(\"plugin:\".length, slashIndex);\n const configName = extendName.slice(slashIndex + 1);\n\n if (isFilePath(pluginName)) {\n throw new Error(\"'extends' cannot use a file path for plugins.\");\n }\n\n const plugin = this._loadPlugin(pluginName, ctx);\n const configData =\n plugin.definition &&\n plugin.definition.configs[configName];\n\n if (configData) {\n return this._normalizeConfigData(configData, {\n ...ctx,\n filePath: plugin.filePath || ctx.filePath,\n name: `${ctx.name} » plugin:${plugin.id}/${configName}`\n });\n }\n\n throw plugin.error || configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedShareableConfig(extendName, ctx) {\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n let request;\n\n if (isFilePath(extendName)) {\n request = extendName;\n } else if (extendName.startsWith(\".\")) {\n request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.\n } else {\n request = naming.normalizePackageName(\n extendName,\n \"eslint-config\"\n );\n }\n\n let filePath;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (error) {\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n throw configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n throw error;\n }\n\n writeDebugLogForLoading(request, relativeTo, filePath);\n return this._loadConfigData({\n ...ctx,\n filePath,\n name: `${ctx.name} » ${request}`\n });\n }\n\n /**\n * Load given plugins.\n * @param {string[]} names The plugin names to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {Record} The loaded parser.\n * @private\n */\n _loadPlugins(names, ctx) {\n return names.reduce((map, name) => {\n if (isFilePath(name)) {\n throw new Error(\"Plugins array cannot includes file paths.\");\n }\n const plugin = this._loadPlugin(name, ctx);\n\n map[plugin.id] = plugin;\n\n return map;\n }, {});\n }\n\n /**\n * Load a given parser.\n * @param {string} nameOrPath The package name or the path to a parser file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentParser} The loaded parser.\n */\n _loadParser(nameOrPath, ctx) {\n debug(\"Loading parser %j from %s\", nameOrPath, ctx.filePath);\n\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n\n try {\n const filePath = resolver.resolve(nameOrPath, relativeTo);\n\n writeDebugLogForLoading(nameOrPath, relativeTo, filePath);\n\n return new ConfigDependency({\n definition: require(filePath),\n filePath,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (error) {\n\n // If the parser name is \"espree\", load the espree of ESLint.\n if (nameOrPath === \"espree\") {\n debug(\"Fallback espree.\");\n return new ConfigDependency({\n definition: require(\"espree\"),\n filePath: require.resolve(\"espree\"),\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n debug(\"Failed to load parser '%s' declared in '%s'.\", nameOrPath, ctx.name);\n error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;\n\n return new ConfigDependency({\n error,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n }\n\n /**\n * Load a given plugin.\n * @param {string} name The plugin name to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentPlugin} The loaded plugin.\n * @private\n */\n _loadPlugin(name, ctx) {\n debug(\"Loading plugin %j from %s\", name, ctx.filePath);\n\n const { additionalPluginPool, resolver } = internalSlotsMap.get(this);\n const request = naming.normalizePackageName(name, \"eslint-plugin\");\n const id = naming.getShorthandName(request, \"eslint-plugin\");\n const relativeTo = path.join(ctx.pluginBasePath, \"__placeholder__.js\");\n\n if (name.match(/\\s+/u)) {\n const error = Object.assign(\n new Error(`Whitespace found in plugin name '${name}'`),\n {\n messageTemplate: \"whitespace-found\",\n messageData: { pluginName: request }\n }\n );\n\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n // Check for additional pool.\n const plugin =\n additionalPluginPool.get(request) ||\n additionalPluginPool.get(id);\n\n if (plugin) {\n return new ConfigDependency({\n definition: normalizePlugin(plugin),\n filePath: \"\", // It's unknown where the plugin came from.\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n let filePath;\n let error;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (resolveError) {\n error = resolveError;\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n error.messageTemplate = \"plugin-missing\";\n error.messageData = {\n pluginName: request,\n resolvePluginsRelativeTo: ctx.pluginBasePath,\n importerName: ctx.name\n };\n }\n }\n\n if (filePath) {\n try {\n writeDebugLogForLoading(request, relativeTo, filePath);\n\n const startTime = Date.now();\n const pluginDefinition = require(filePath);\n\n debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);\n\n return new ConfigDependency({\n definition: normalizePlugin(pluginDefinition),\n filePath,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (loadError) {\n error = loadError;\n }\n }\n\n debug(\"Failed to load plugin '%s' declared in '%s'.\", name, ctx.name);\n error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n /**\n * Take file expression processors as config array elements.\n * @param {Record} plugins The plugin definitions.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The config array elements of file expression processors.\n * @private\n */\n *_takeFileExtensionProcessors(plugins, ctx) {\n for (const pluginId of Object.keys(plugins)) {\n const processors =\n plugins[pluginId] &&\n plugins[pluginId].definition &&\n plugins[pluginId].definition.processors;\n\n if (!processors) {\n continue;\n }\n\n for (const processorId of Object.keys(processors)) {\n if (processorId.startsWith(\".\")) {\n yield* this._normalizeObjectConfigData(\n {\n files: [`*${processorId}`],\n processor: `${pluginId}/${processorId}`\n },\n {\n ...ctx,\n type: \"implicit-processor\",\n name: `${ctx.name}#processors[\"${pluginId}/${processorId}\"]`\n }\n );\n }\n }\n }\n }\n}\n\nexport { ConfigArrayFactory, createContext };\n","/**\n * @fileoverview `CascadingConfigArrayFactory` class.\n *\n * `CascadingConfigArrayFactory` class has a responsibility:\n *\n * 1. Handles cascading of config files.\n *\n * It provides two methods:\n *\n * - `getConfigArrayForFile(filePath)`\n * Get the corresponded configuration of a given file. This method doesn't\n * throw even if the given file didn't exist.\n * - `clearCache()`\n * Clear the internal cache. You have to call this method when\n * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends\n * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport { emitDeprecationWarning } from \"./shared/deprecation-warnings.js\";\n\nconst debug = debugOrig(\"eslintrc:cascading-config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {ReturnType} ConfigArray */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {ConfigData} [baseConfig] The config by `baseConfig` option.\n * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.\n * @property {string} [cwd] The base directory to start lookup.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]} [rulePaths] The value of `--rulesdir` option.\n * @property {string} [specificConfigPath] The value of `--config` option.\n * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryInternalSlots\n * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.\n * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.\n * @property {ConfigArray} cliConfigArray The config array of CLI options.\n * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.\n * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.\n * @property {Map} configCache The cache from directory paths to config arrays.\n * @property {string} cwd The base directory to start lookup.\n * @property {WeakMap} finalizeCache The cache from config arrays to finalized config arrays.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.\n * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.\n * @property {boolean} useEslintrc if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Create the config array from `baseConfig` and `rulePaths`.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createBaseConfigArray({\n configArrayFactory,\n baseConfigData,\n rulePaths,\n cwd,\n loadRules\n}) {\n const baseConfigArray = configArrayFactory.create(\n baseConfigData,\n { name: \"BaseConfig\" }\n );\n\n /*\n * Create the config array element for the default ignore patterns.\n * This element has `ignorePattern` property that ignores the default\n * patterns in the current working directory.\n */\n baseConfigArray.unshift(configArrayFactory.create(\n { ignorePatterns: IgnorePattern.DefaultPatterns },\n { name: \"DefaultIgnorePattern\" }\n )[0]);\n\n /*\n * Load rules `--rulesdir` option as a pseudo plugin.\n * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate\n * the rule's options with only information in the config array.\n */\n if (rulePaths && rulePaths.length > 0) {\n baseConfigArray.push({\n type: \"config\",\n name: \"--rulesdir\",\n filePath: \"\",\n plugins: {\n \"\": new ConfigDependency({\n definition: {\n rules: rulePaths.reduce(\n (map, rulesPath) => Object.assign(\n map,\n loadRules(rulesPath, cwd)\n ),\n {}\n )\n },\n filePath: \"\",\n id: \"\",\n importerName: \"--rulesdir\",\n importerPath: \"\"\n })\n }\n });\n }\n\n return baseConfigArray;\n}\n\n/**\n * Create the config array from CLI options.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n}) {\n const cliConfigArray = configArrayFactory.create(\n cliConfigData,\n { name: \"CLIOptions\" }\n );\n\n cliConfigArray.unshift(\n ...(ignorePath\n ? configArrayFactory.loadESLintIgnore(ignorePath)\n : configArrayFactory.loadDefaultESLintIgnore())\n );\n\n if (specificConfigPath) {\n cliConfigArray.unshift(\n ...configArrayFactory.loadFile(\n specificConfigPath,\n { name: \"--config\", basePath: cwd }\n )\n );\n }\n\n return cliConfigArray;\n}\n\n/**\n * The error type when there are files matched by a glob, but all of them have been ignored.\n */\nclass ConfigurationNotFoundError extends Error {\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @param {string} directoryPath The directory path.\n */\n constructor(directoryPath) {\n super(`No ESLint configuration found in ${directoryPath}.`);\n this.messageTemplate = \"no-config-found\";\n this.messageData = { directoryPath };\n }\n}\n\n/**\n * This class provides the functionality that enumerates every file which is\n * matched by given glob patterns and that configuration.\n */\nclass CascadingConfigArrayFactory {\n\n /**\n * Initialize this enumerator.\n * @param {CascadingConfigArrayFactoryOptions} options The options.\n */\n constructor({\n additionalPluginPool = new Map(),\n baseConfig: baseConfigData = null,\n cliConfig: cliConfigData = null,\n cwd = process.cwd(),\n ignorePath,\n resolvePluginsRelativeTo,\n rulePaths = [],\n specificConfigPath = null,\n useEslintrc = true,\n builtInRules = new Map(),\n loadRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n } = {}) {\n const configArrayFactory = new ConfigArrayFactory({\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo,\n builtInRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n });\n\n internalSlotsMap.set(this, {\n baseConfigArray: createBaseConfigArray({\n baseConfigData,\n configArrayFactory,\n cwd,\n rulePaths,\n loadRules,\n resolver\n }),\n baseConfigData,\n cliConfigArray: createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n }),\n cliConfigData,\n configArrayFactory,\n configCache: new Map(),\n cwd,\n finalizeCache: new WeakMap(),\n ignorePath,\n rulePaths,\n specificConfigPath,\n useEslintrc,\n builtInRules,\n loadRules\n });\n }\n\n /**\n * The path to the current working directory.\n * This is used by tests.\n * @type {string}\n */\n get cwd() {\n const { cwd } = internalSlotsMap.get(this);\n\n return cwd;\n }\n\n /**\n * Get the config array of a given file.\n * If `filePath` was not given, it returns the config which contains only\n * `baseConfigData` and `cliConfigData`.\n * @param {string} [filePath] The file path to a file.\n * @param {Object} [options] The options.\n * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The config array of the file.\n */\n getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {\n const {\n baseConfigArray,\n cliConfigArray,\n cwd\n } = internalSlotsMap.get(this);\n\n if (!filePath) {\n return new ConfigArray(...baseConfigArray, ...cliConfigArray);\n }\n\n const directoryPath = path.dirname(path.resolve(cwd, filePath));\n\n debug(`Load config files for ${directoryPath}.`);\n\n return this._finalizeConfigArray(\n this._loadConfigInAncestors(directoryPath),\n directoryPath,\n ignoreNotFoundError\n );\n }\n\n /**\n * Set the config data to override all configs.\n * Require to call `clearCache()` method after this method is called.\n * @param {ConfigData} configData The config data to override all configs.\n * @returns {void}\n */\n setOverrideConfig(configData) {\n const slots = internalSlotsMap.get(this);\n\n slots.cliConfigData = configData;\n }\n\n /**\n * Clear config cache.\n * @returns {void}\n */\n clearCache() {\n const slots = internalSlotsMap.get(this);\n\n slots.baseConfigArray = createBaseConfigArray(slots);\n slots.cliConfigArray = createCLIConfigArray(slots);\n slots.configCache.clear();\n }\n\n /**\n * Load and normalize config files from the ancestor directories.\n * @param {string} directoryPath The path to a leaf directory.\n * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {\n const {\n baseConfigArray,\n configArrayFactory,\n configCache,\n cwd,\n useEslintrc\n } = internalSlotsMap.get(this);\n\n if (!useEslintrc) {\n return baseConfigArray;\n }\n\n let configArray = configCache.get(directoryPath);\n\n // Hit cache.\n if (configArray) {\n debug(`Cache hit: ${directoryPath}.`);\n return configArray;\n }\n debug(`No cache found: ${directoryPath}.`);\n\n const homePath = os.homedir();\n\n // Consider this is root.\n if (directoryPath === homePath && cwd !== homePath) {\n debug(\"Stop traversing because of considered root.\");\n if (configsExistInSubdirs) {\n const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);\n\n if (filePath) {\n emitDeprecationWarning(\n filePath,\n \"ESLINT_PERSONAL_CONFIG_SUPPRESS\"\n );\n }\n }\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n\n // Load the config on this directory.\n try {\n configArray = configArrayFactory.loadInDirectory(directoryPath);\n } catch (error) {\n /* istanbul ignore next */\n if (error.code === \"EACCES\") {\n debug(\"Stop traversing because of 'EACCES' error.\");\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n throw error;\n }\n\n if (configArray.length > 0 && configArray.isRoot()) {\n debug(\"Stop traversing because of 'root:true'.\");\n configArray.unshift(...baseConfigArray);\n return this._cacheConfig(directoryPath, configArray);\n }\n\n // Load from the ancestors and merge it.\n const parentPath = path.dirname(directoryPath);\n const parentConfigArray = parentPath && parentPath !== directoryPath\n ? this._loadConfigInAncestors(\n parentPath,\n configsExistInSubdirs || configArray.length > 0\n )\n : baseConfigArray;\n\n if (configArray.length > 0) {\n configArray.unshift(...parentConfigArray);\n } else {\n configArray = parentConfigArray;\n }\n\n // Cache and return.\n return this._cacheConfig(directoryPath, configArray);\n }\n\n /**\n * Freeze and cache a given config.\n * @param {string} directoryPath The path to a directory as a cache key.\n * @param {ConfigArray} configArray The config array as a cache value.\n * @returns {ConfigArray} The `configArray` (frozen).\n */\n _cacheConfig(directoryPath, configArray) {\n const { configCache } = internalSlotsMap.get(this);\n\n Object.freeze(configArray);\n configCache.set(directoryPath, configArray);\n\n return configArray;\n }\n\n /**\n * Finalize a given config array.\n * Concatenate `--config` and other CLI options.\n * @param {ConfigArray} configArray The parent config array.\n * @param {string} directoryPath The path to the leaf directory to find config files.\n * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {\n const {\n cliConfigArray,\n configArrayFactory,\n finalizeCache,\n useEslintrc,\n builtInRules\n } = internalSlotsMap.get(this);\n\n let finalConfigArray = finalizeCache.get(configArray);\n\n if (!finalConfigArray) {\n finalConfigArray = configArray;\n\n // Load the personal config if there are no regular config files.\n if (\n useEslintrc &&\n configArray.every(c => !c.filePath) &&\n cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.\n ) {\n const homePath = os.homedir();\n\n debug(\"Loading the config file of the home directory:\", homePath);\n\n const personalConfigArray = configArrayFactory.loadInDirectory(\n homePath,\n { name: \"PersonalConfig\" }\n );\n\n if (\n personalConfigArray.length > 0 &&\n !directoryPath.startsWith(homePath)\n ) {\n const lastElement =\n personalConfigArray[personalConfigArray.length - 1];\n\n emitDeprecationWarning(\n lastElement.filePath,\n \"ESLINT_PERSONAL_CONFIG_LOAD\"\n );\n }\n\n finalConfigArray = finalConfigArray.concat(personalConfigArray);\n }\n\n // Apply CLI options.\n if (cliConfigArray.length > 0) {\n finalConfigArray = finalConfigArray.concat(cliConfigArray);\n }\n\n // Validate rule settings and environments.\n const validator = new ConfigValidator({\n builtInRules\n });\n\n validator.validateConfigArray(finalConfigArray);\n\n // Cache it.\n Object.freeze(finalConfigArray);\n finalizeCache.set(configArray, finalConfigArray);\n\n debug(\n \"Configuration was determined: %o on %s\",\n finalConfigArray,\n directoryPath\n );\n }\n\n // At least one element (the default ignore patterns) exists.\n if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {\n throw new ConfigurationNotFoundError(directoryPath);\n }\n\n return finalConfigArray;\n }\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport { CascadingConfigArrayFactory };\n","/**\n * @fileoverview Compatibility class for flat config.\n * @author Nicholas C. Zakas\n */\n\n//-----------------------------------------------------------------------------\n// Requirements\n//-----------------------------------------------------------------------------\n\nimport createDebug from \"debug\";\nimport path from \"path\";\n\nimport environments from \"../conf/environments.js\";\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n\nconst debug = createDebug(\"eslintrc:flat-compat\");\nconst cafactory = Symbol(\"cafactory\");\n\n/**\n * Translates an ESLintRC-style config object into a flag-config-style config\n * object.\n * @param {Object} eslintrcConfig An ESLintRC-style config object.\n * @param {Object} options Options to help translate the config.\n * @param {string} options.resolveConfigRelativeTo To the directory to resolve\n * configs from.\n * @param {string} options.resolvePluginsRelativeTo The directory to resolve\n * plugins from.\n * @param {ReadOnlyMap} options.pluginEnvironments A map of plugin environment\n * names to objects.\n * @param {ReadOnlyMap} options.pluginProcessors A map of plugin processor\n * names to objects.\n * @returns {Object} A flag-config-style config object.\n */\nfunction translateESLintRC(eslintrcConfig, {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo,\n pluginEnvironments,\n pluginProcessors\n}) {\n\n const flatConfig = {};\n const configs = [];\n const languageOptions = {};\n const linterOptions = {};\n const keysToCopy = [\"settings\", \"rules\", \"processor\"];\n const languageOptionsKeysToCopy = [\"globals\", \"parser\", \"parserOptions\"];\n const linterOptionsKeysToCopy = [\"noInlineConfig\", \"reportUnusedDisableDirectives\"];\n\n // check for special settings for eslint:all and eslint:recommended:\n if (eslintrcConfig.settings) {\n if (eslintrcConfig.settings[\"eslint:all\"] === true) {\n return [\"eslint:all\"];\n }\n\n if (eslintrcConfig.settings[\"eslint:recommended\"] === true) {\n return [\"eslint:recommended\"];\n }\n }\n\n // copy over simple translations\n for (const key of keysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig[key] = eslintrcConfig[key];\n }\n }\n\n // copy over languageOptions\n for (const key of languageOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n\n // create the languageOptions key in the flat config\n flatConfig.languageOptions = languageOptions;\n\n if (key === \"parser\") {\n debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);\n\n if (eslintrcConfig[key].error) {\n throw eslintrcConfig[key].error;\n }\n\n languageOptions[key] = eslintrcConfig[key].definition;\n continue;\n }\n\n // clone any object values that are in the eslintrc config\n if (eslintrcConfig[key] && typeof eslintrcConfig[key] === \"object\") {\n languageOptions[key] = {\n ...eslintrcConfig[key]\n };\n } else {\n languageOptions[key] = eslintrcConfig[key];\n }\n }\n }\n\n // copy over linterOptions\n for (const key of linterOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig.linterOptions = linterOptions;\n linterOptions[key] = eslintrcConfig[key];\n }\n }\n\n // move ecmaVersion a level up\n if (languageOptions.parserOptions) {\n\n if (\"ecmaVersion\" in languageOptions.parserOptions) {\n languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;\n delete languageOptions.parserOptions.ecmaVersion;\n }\n\n if (\"sourceType\" in languageOptions.parserOptions) {\n languageOptions.sourceType = languageOptions.parserOptions.sourceType;\n delete languageOptions.parserOptions.sourceType;\n }\n\n // check to see if we even need parserOptions anymore and remove it if not\n if (Object.keys(languageOptions.parserOptions).length === 0) {\n delete languageOptions.parserOptions;\n }\n }\n\n // overrides\n if (eslintrcConfig.criteria) {\n flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];\n }\n\n // translate plugins\n if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === \"object\") {\n debug(`Translating plugins: ${eslintrcConfig.plugins}`);\n\n flatConfig.plugins = {};\n\n for (const pluginName of Object.keys(eslintrcConfig.plugins)) {\n\n debug(`Translating plugin: ${pluginName}`);\n debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);\n\n const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];\n\n if (error) {\n throw error;\n }\n\n flatConfig.plugins[pluginName] = plugin;\n\n // create a config for any processors\n if (plugin.processors) {\n for (const processorName of Object.keys(plugin.processors)) {\n if (processorName.startsWith(\".\")) {\n debug(`Assigning processor: ${pluginName}/${processorName}`);\n\n configs.unshift({\n files: [`**/*${processorName}`],\n processor: pluginProcessors.get(`${pluginName}/${processorName}`)\n });\n }\n\n }\n }\n }\n }\n\n // translate env - must come after plugins\n if (eslintrcConfig.env && typeof eslintrcConfig.env === \"object\") {\n for (const envName of Object.keys(eslintrcConfig.env)) {\n\n // only add environments that are true\n if (eslintrcConfig.env[envName]) {\n debug(`Translating environment: ${envName}`);\n\n if (environments.has(envName)) {\n\n // built-in environments should be defined first\n configs.unshift(...translateESLintRC(environments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n } else if (pluginEnvironments.has(envName)) {\n\n // if the environment comes from a plugin, it should come after the plugin config\n configs.push(...translateESLintRC(pluginEnvironments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n }\n }\n }\n }\n\n // only add if there are actually keys in the config\n if (Object.keys(flatConfig).length > 0) {\n configs.push(flatConfig);\n }\n\n return configs;\n}\n\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\n/**\n * A compatibility class for working with configs.\n */\nclass FlatCompat {\n\n constructor({\n baseDirectory = process.cwd(),\n resolvePluginsRelativeTo = baseDirectory\n } = {}) {\n this.baseDirectory = baseDirectory;\n this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;\n this[cafactory] = new ConfigArrayFactory({\n cwd: baseDirectory,\n resolvePluginsRelativeTo,\n getEslintAllConfig: () => ({ settings: { \"eslint:all\": true } }),\n getEslintRecommendedConfig: () => ({ settings: { \"eslint:recommended\": true } })\n });\n }\n\n /**\n * Translates an ESLintRC-style config into a flag-config-style config.\n * @param {Object} eslintrcConfig The ESLintRC-style config object.\n * @returns {Object} A flag-config-style config object.\n */\n config(eslintrcConfig) {\n const eslintrcArray = this[cafactory].create(eslintrcConfig, {\n basePath: this.baseDirectory\n });\n\n const flatArray = [];\n let hasIgnorePatterns = false;\n\n eslintrcArray.forEach(configData => {\n if (configData.type === \"config\") {\n hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;\n flatArray.push(...translateESLintRC(configData, {\n resolveConfigRelativeTo: path.join(this.baseDirectory, \"__placeholder.js\"),\n resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, \"__placeholder.js\"),\n pluginEnvironments: eslintrcArray.pluginEnvironments,\n pluginProcessors: eslintrcArray.pluginProcessors\n }));\n }\n });\n\n // combine ignorePatterns to emulate ESLintRC behavior better\n if (hasIgnorePatterns) {\n flatArray.unshift({\n ignores: [filePath => {\n\n // Compute the final config for this file.\n // This filters config array elements by `files`/`excludedFiles` then merges the elements.\n const finalConfig = eslintrcArray.extractConfig(filePath);\n\n // Test the `ignorePattern` properties of the final config.\n return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);\n }]\n });\n }\n\n return flatArray;\n }\n\n /**\n * Translates the `env` section of an ESLintRC-style config.\n * @param {Object} envConfig The `env` section of an ESLintRC config.\n * @returns {Object} A flag-config object representing the environments.\n */\n env(envConfig) {\n return this.config({\n env: envConfig\n });\n }\n\n /**\n * Translates the `extends` section of an ESLintRC-style config.\n * @param {...string} configsToExtend The names of the configs to load.\n * @returns {Object} A flag-config object representing the config.\n */\n extends(...configsToExtend) {\n return this.config({\n extends: configsToExtend\n });\n }\n\n /**\n * Translates the `plugins` section of an ESLintRC-style config.\n * @param {...string} plugins The names of the plugins to load.\n * @returns {Object} A flag-config object representing the plugins.\n */\n plugins(...plugins) {\n return this.config({\n plugins\n });\n }\n}\n\nexport { FlatCompat };\n","/**\n * @fileoverview Package exports for @eslint/eslintrc\n * @author Nicholas C. Zakas\n */\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport {\n ConfigArrayFactory,\n createContext as createConfigArrayFactoryContext\n} from \"./config-array-factory.js\";\n\nimport { CascadingConfigArrayFactory } from \"./cascading-config-array-factory.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array/index.js\";\nimport { ConfigDependency } from \"./config-array/config-dependency.js\";\nimport { ExtractedConfig } from \"./config-array/extracted-config.js\";\nimport { IgnorePattern } from \"./config-array/ignore-pattern.js\";\nimport { OverrideTester } from \"./config-array/override-tester.js\";\nimport * as ConfigOps from \"./shared/config-ops.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport { FlatCompat } from \"./flat-compat.js\";\nimport environments from \"../conf/environments.js\";\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nconst Legacy = {\n ConfigArray,\n createConfigArrayFactoryContext,\n CascadingConfigArrayFactory,\n ConfigArrayFactory,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs,\n environments,\n\n // shared\n ConfigOps,\n ConfigValidator,\n ModuleResolver,\n naming\n};\n\nexport {\n\n Legacy,\n\n FlatCompat\n\n};\n"],"names":["debug","debugOrig","path","ignore","assert","internalSlotsMap","util","minimatch","Ajv","globals","BuiltInEnvironments","ConfigOps.normalizeConfigGlobal","Module","require","createRequire","fs","stripComments","importFresh","ModuleResolver.resolve","naming.normalizePackageName","naming.getShorthandName","os","createDebug","createConfigArrayFactoryContext"],"mappings":"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"} -\ No newline at end of file -+{"version":3,"file":"eslintrc.cjs","sources":["../lib/config-array/ignore-pattern.js","../lib/config-array/extracted-config.js","../lib/config-array/config-array.js","../lib/config-array/config-dependency.js","../lib/config-array/override-tester.js","../lib/config-array/index.js","../lib/shared/config-ops.js","../lib/shared/deprecation-warnings.js","../lib/shared/ajv.js","../conf/config-schema.js","../conf/environments.js","../lib/shared/config-validator.js","../lib/shared/naming.js","../lib/shared/relative-module-resolver.js","../lib/config-array-factory.js","../lib/cascading-config-array-factory.js","../lib/flat-compat.js","../lib/index.js"],"sourcesContent":["/**\n * @fileoverview `IgnorePattern` class.\n *\n * `IgnorePattern` class has the set of glob patterns and the base path.\n *\n * It provides two static methods.\n *\n * - `IgnorePattern.createDefaultIgnore(cwd)`\n * Create the default predicate function.\n * - `IgnorePattern.createIgnore(ignorePatterns)`\n * Create the predicate function from multiple `IgnorePattern` objects.\n *\n * It provides two properties and a method.\n *\n * - `patterns`\n * The glob patterns that ignore to lint.\n * - `basePath`\n * The base path of the glob patterns. If absolute paths existed in the\n * glob patterns, those are handled as relative paths to the base path.\n * - `getPatternsRelativeTo(basePath)`\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n *\n * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes\n * `ignorePatterns` properties.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport ignore from \"ignore\";\nimport debugOrig from \"debug\";\n\nconst debug = debugOrig(\"eslintrc:ignore-pattern\");\n\n/** @typedef {ReturnType} Ignore */\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the path to the common ancestor directory of given paths.\n * @param {string[]} sourcePaths The paths to calculate the common ancestor.\n * @returns {string} The path to the common ancestor directory.\n */\nfunction getCommonAncestorPath(sourcePaths) {\n let result = sourcePaths[0];\n\n for (let i = 1; i < sourcePaths.length; ++i) {\n const a = result;\n const b = sourcePaths[i];\n\n // Set the shorter one (it's the common ancestor if one includes the other).\n result = a.length < b.length ? a : b;\n\n // Set the common ancestor.\n for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {\n if (a[j] !== b[j]) {\n result = a.slice(0, lastSepPos);\n break;\n }\n if (a[j] === path.sep) {\n lastSepPos = j;\n }\n }\n }\n\n let resolvedResult = result || path.sep;\n\n // if Windows common ancestor is root of drive must have trailing slash to be absolute.\n if (resolvedResult && resolvedResult.endsWith(\":\") && process.platform === \"win32\") {\n resolvedResult += path.sep;\n }\n return resolvedResult;\n}\n\n/**\n * Make relative path.\n * @param {string} from The source path to get relative path.\n * @param {string} to The destination path to get relative path.\n * @returns {string} The relative path.\n */\nfunction relative(from, to) {\n const relPath = path.relative(from, to);\n\n if (path.sep === \"/\") {\n return relPath;\n }\n return relPath.split(path.sep).join(\"/\");\n}\n\n/**\n * Get the trailing slash if existed.\n * @param {string} filePath The path to check.\n * @returns {string} The trailing slash if existed.\n */\nfunction dirSuffix(filePath) {\n const isDir = (\n filePath.endsWith(path.sep) ||\n (process.platform === \"win32\" && filePath.endsWith(\"/\"))\n );\n\n return isDir ? \"/\" : \"\";\n}\n\nconst DefaultPatterns = Object.freeze([\"/**/node_modules/*\"]);\nconst DotPatterns = Object.freeze([\".*\", \"!.eslintrc.*\", \"!../\"]);\n\n//------------------------------------------------------------------------------\n// Public\n//------------------------------------------------------------------------------\n\nclass IgnorePattern {\n\n /**\n * The default patterns.\n * @type {string[]}\n */\n static get DefaultPatterns() {\n return DefaultPatterns;\n }\n\n /**\n * Create the default predicate function.\n * @param {string} cwd The current working directory.\n * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createDefaultIgnore(cwd) {\n return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);\n }\n\n /**\n * Create the predicate function from multiple `IgnorePattern` objects.\n * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.\n * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createIgnore(ignorePatterns) {\n debug(\"Create with: %o\", ignorePatterns);\n\n const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));\n const patterns = [].concat(\n ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))\n );\n const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);\n const dotIg = ignore({ allowRelativePaths: true }).add(patterns);\n\n debug(\" processed: %o\", { basePath, patterns });\n\n return Object.assign(\n (filePath, dot = false) => {\n assert(path.isAbsolute(filePath), \"'filePath' should be an absolute path.\");\n const relPathRaw = relative(basePath, filePath);\n const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));\n const adoptedIg = dot ? dotIg : ig;\n const result = relPath !== \"\" && adoptedIg.ignores(relPath);\n\n debug(\"Check\", { filePath, dot, relativePath: relPath, result });\n return result;\n },\n { basePath, patterns }\n );\n }\n\n /**\n * Initialize a new `IgnorePattern` instance.\n * @param {string[]} patterns The glob patterns that ignore to lint.\n * @param {string} basePath The base path of `patterns`.\n */\n constructor(patterns, basePath) {\n assert(path.isAbsolute(basePath), \"'basePath' should be an absolute path.\");\n\n /**\n * The glob patterns that ignore to lint.\n * @type {string[]}\n */\n this.patterns = patterns;\n\n /**\n * The base path of `patterns`.\n * @type {string}\n */\n this.basePath = basePath;\n\n /**\n * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.\n *\n * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.\n * It's `false` as-is for `ignorePatterns` property in config files.\n * @type {boolean}\n */\n this.loose = false;\n }\n\n /**\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n * @param {string} newBasePath The base path.\n * @returns {string[]} Modifired patterns.\n */\n getPatternsRelativeTo(newBasePath) {\n assert(path.isAbsolute(newBasePath), \"'newBasePath' should be an absolute path.\");\n const { basePath, loose, patterns } = this;\n\n if (newBasePath === basePath) {\n return patterns;\n }\n const prefix = `/${relative(newBasePath, basePath)}`;\n\n return patterns.map(pattern => {\n const negative = pattern.startsWith(\"!\");\n const head = negative ? \"!\" : \"\";\n const body = negative ? pattern.slice(1) : pattern;\n\n if (body.startsWith(\"/\") || body.startsWith(\"../\")) {\n return `${head}${prefix}${body}`;\n }\n return loose ? pattern : `${head}${prefix}/**/${body}`;\n });\n }\n}\n\nexport { IgnorePattern };\n","/**\n * @fileoverview `ExtractedConfig` class.\n *\n * `ExtractedConfig` class expresses a final configuration for a specific file.\n *\n * It provides one method.\n *\n * - `toCompatibleObjectAsConfigFileContent()`\n * Convert this configuration to the compatible object as the content of\n * config files. It converts the loaded parser and plugins to strings.\n * `CLIEngine#getConfigForFile(filePath)` method uses this method.\n *\n * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.\n *\n * @author Toru Nagashima \n */\n\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n// For VSCode intellisense\n/** @typedef {import(\"../../shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").SeverityConf} SeverityConf */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n\n/**\n * Check if `xs` starts with `ys`.\n * @template T\n * @param {T[]} xs The array to check.\n * @param {T[]} ys The array that may be the first part of `xs`.\n * @returns {boolean} `true` if `xs` starts with `ys`.\n */\nfunction startsWith(xs, ys) {\n return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);\n}\n\n/**\n * The class for extracted config data.\n */\nclass ExtractedConfig {\n constructor() {\n\n /**\n * The config name what `noInlineConfig` setting came from.\n * @type {string}\n */\n this.configNameOfNoInlineConfig = \"\";\n\n /**\n * Environments.\n * @type {Record}\n */\n this.env = {};\n\n /**\n * Global variables.\n * @type {Record}\n */\n this.globals = {};\n\n /**\n * The glob patterns that ignore to lint.\n * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}\n */\n this.ignores = void 0;\n\n /**\n * The flag that disables directive comments.\n * @type {boolean|undefined}\n */\n this.noInlineConfig = void 0;\n\n /**\n * Parser definition.\n * @type {DependentParser|null}\n */\n this.parser = null;\n\n /**\n * Options for the parser.\n * @type {Object}\n */\n this.parserOptions = {};\n\n /**\n * Plugin definitions.\n * @type {Record}\n */\n this.plugins = {};\n\n /**\n * Processor ID.\n * @type {string|null}\n */\n this.processor = null;\n\n /**\n * The flag that reports unused `eslint-disable` directive comments.\n * @type {boolean|undefined}\n */\n this.reportUnusedDisableDirectives = void 0;\n\n /**\n * Rule settings.\n * @type {Record}\n */\n this.rules = {};\n\n /**\n * Shared settings.\n * @type {Object}\n */\n this.settings = {};\n }\n\n /**\n * Convert this config to the compatible object as a config file content.\n * @returns {ConfigData} The converted object.\n */\n toCompatibleObjectAsConfigFileContent() {\n const {\n /* eslint-disable no-unused-vars */\n configNameOfNoInlineConfig: _ignore1,\n processor: _ignore2,\n /* eslint-enable no-unused-vars */\n ignores,\n ...config\n } = this;\n\n config.parser = config.parser && config.parser.filePath;\n config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();\n config.ignorePatterns = ignores ? ignores.patterns : [];\n\n // Strip the default patterns from `ignorePatterns`.\n if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {\n config.ignorePatterns =\n config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);\n }\n\n return config;\n }\n}\n\nexport { ExtractedConfig };\n","/**\n * @fileoverview `ConfigArray` class.\n *\n * `ConfigArray` class expresses the full of a configuration. It has the entry\n * config file, base config files that were extended, loaded parsers, and loaded\n * plugins.\n *\n * `ConfigArray` class provides three properties and two methods.\n *\n * - `pluginEnvironments`\n * - `pluginProcessors`\n * - `pluginRules`\n * The `Map` objects that contain the members of all plugins that this\n * config array contains. Those map objects don't have mutation methods.\n * Those keys are the member ID such as `pluginId/memberName`.\n * - `isRoot()`\n * If `true` then this configuration has `root:true` property.\n * - `extractConfig(filePath)`\n * Extract the final configuration for a given file. This means merging\n * every config array element which that `criteria` property matched. The\n * `filePath` argument must be an absolute path.\n *\n * `ConfigArrayFactory` provides the loading logic of config files.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").RuleConf} RuleConf */\n/** @typedef {import(\"../../shared/types\").Rule} Rule */\n/** @typedef {import(\"../../shared/types\").Plugin} Plugin */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {import(\"./override-tester\")[\"OverrideTester\"]} OverrideTester */\n\n/**\n * @typedef {Object} ConfigArrayElement\n * @property {string} name The name of this config element.\n * @property {string} filePath The path to the source file of this config element.\n * @property {InstanceType|null} criteria The tester for the `files` and `excludedFiles` of this config element.\n * @property {Record|undefined} env The environment settings.\n * @property {Record|undefined} globals The global variable settings.\n * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.\n * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.\n * @property {DependentParser|undefined} parser The parser loader.\n * @property {Object|undefined} parserOptions The parser options.\n * @property {Record|undefined} plugins The plugin loaders.\n * @property {string|undefined} processor The processor name to refer plugin's processor.\n * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.\n * @property {boolean|undefined} root The flag to express root.\n * @property {Record|undefined} rules The rule settings\n * @property {Object|undefined} settings The shared settings.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The element type.\n */\n\n/**\n * @typedef {Object} ConfigArrayInternalSlots\n * @property {Map} cache The cache to extract configs.\n * @property {ReadonlyMap|null} envMap The map from environment ID to environment definition.\n * @property {ReadonlyMap|null} processorMap The map from processor ID to environment definition.\n * @property {ReadonlyMap|null} ruleMap The map from rule ID to rule definition.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new class extends WeakMap {\n get(key) {\n let value = super.get(key);\n\n if (!value) {\n value = {\n cache: new Map(),\n envMap: null,\n processorMap: null,\n ruleMap: null\n };\n super.set(key, value);\n }\n\n return value;\n }\n}();\n\n/**\n * Get the indices which are matched to a given file.\n * @param {ConfigArrayElement[]} elements The elements.\n * @param {string} filePath The path to a target file.\n * @returns {number[]} The indices.\n */\nfunction getMatchedIndices(elements, filePath) {\n const indices = [];\n\n for (let i = elements.length - 1; i >= 0; --i) {\n const element = elements[i];\n\n if (!element.criteria || (filePath && element.criteria.test(filePath))) {\n indices.push(i);\n }\n }\n\n return indices;\n}\n\n/**\n * Check if a value is a non-null object.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is a non-null object.\n */\nfunction isNonNullObject(x) {\n return typeof x === \"object\" && x !== null;\n}\n\n/**\n * Merge two objects.\n *\n * Assign every property values of `y` to `x` if `x` doesn't have the property.\n * If `x`'s property value is an object, it does recursive.\n * @param {Object} target The destination to merge\n * @param {Object|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeWithoutOverwrite(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n\n if (isNonNullObject(target[key])) {\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (target[key] === void 0) {\n if (isNonNullObject(source[key])) {\n target[key] = Array.isArray(source[key]) ? [] : {};\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (source[key] !== void 0) {\n target[key] = source[key];\n }\n }\n }\n}\n\n/**\n * The error for plugin conflicts.\n */\nclass PluginConflictError extends Error {\n\n /**\n * Initialize this error object.\n * @param {string} pluginId The plugin ID.\n * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.\n */\n constructor(pluginId, plugins) {\n super(`Plugin \"${pluginId}\" was conflicted between ${plugins.map(p => `\"${p.importerName}\"`).join(\" and \")}.`);\n this.messageTemplate = \"plugin-conflict\";\n this.messageData = { pluginId, plugins };\n }\n}\n\n/**\n * Merge plugins.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergePlugins(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetValue = target[key];\n const sourceValue = source[key];\n\n // Adopt the plugin which was found at first.\n if (targetValue === void 0) {\n if (sourceValue.error) {\n throw sourceValue.error;\n }\n target[key] = sourceValue;\n } else if (sourceValue.filePath !== targetValue.filePath) {\n throw new PluginConflictError(key, [\n {\n filePath: targetValue.filePath,\n importerName: targetValue.importerName\n },\n {\n filePath: sourceValue.filePath,\n importerName: sourceValue.importerName\n }\n ]);\n }\n }\n}\n\n/**\n * Merge rule configs.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeRuleConfigs(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetDef = target[key];\n const sourceDef = source[key];\n\n // Adopt the rule config which was found at first.\n if (targetDef === void 0) {\n if (Array.isArray(sourceDef)) {\n target[key] = [...sourceDef];\n } else {\n target[key] = [sourceDef];\n }\n\n /*\n * If the first found rule config is severity only and the current rule\n * config has options, merge the severity and the options.\n */\n } else if (\n targetDef.length === 1 &&\n Array.isArray(sourceDef) &&\n sourceDef.length >= 2\n ) {\n targetDef.push(...sourceDef.slice(1));\n }\n }\n}\n\n/**\n * Create the extracted config.\n * @param {ConfigArray} instance The config elements.\n * @param {number[]} indices The indices to use.\n * @returns {ExtractedConfig} The extracted config.\n */\nfunction createConfig(instance, indices) {\n const config = new ExtractedConfig();\n const ignorePatterns = [];\n\n // Merge elements.\n for (const index of indices) {\n const element = instance[index];\n\n // Adopt the parser which was found at first.\n if (!config.parser && element.parser) {\n if (element.parser.error) {\n throw element.parser.error;\n }\n config.parser = element.parser;\n }\n\n // Adopt the processor which was found at first.\n if (!config.processor && element.processor) {\n config.processor = element.processor;\n }\n\n // Adopt the noInlineConfig which was found at first.\n if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {\n config.noInlineConfig = element.noInlineConfig;\n config.configNameOfNoInlineConfig = element.name;\n }\n\n // Adopt the reportUnusedDisableDirectives which was found at first.\n if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {\n config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;\n }\n\n // Collect ignorePatterns\n if (element.ignorePattern) {\n ignorePatterns.push(element.ignorePattern);\n }\n\n // Merge others.\n mergeWithoutOverwrite(config.env, element.env);\n mergeWithoutOverwrite(config.globals, element.globals);\n mergeWithoutOverwrite(config.parserOptions, element.parserOptions);\n mergeWithoutOverwrite(config.settings, element.settings);\n mergePlugins(config.plugins, element.plugins);\n mergeRuleConfigs(config.rules, element.rules);\n }\n\n // Create the predicate function for ignore patterns.\n if (ignorePatterns.length > 0) {\n config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());\n }\n\n return config;\n}\n\n/**\n * Collect definitions.\n * @template T, U\n * @param {string} pluginId The plugin ID for prefix.\n * @param {Record} defs The definitions to collect.\n * @param {Map} map The map to output.\n * @param {function(T): U} [normalize] The normalize function for each value.\n * @returns {void}\n */\nfunction collect(pluginId, defs, map, normalize) {\n if (defs) {\n const prefix = pluginId && `${pluginId}/`;\n\n for (const [key, value] of Object.entries(defs)) {\n map.set(\n `${prefix}${key}`,\n normalize ? normalize(value) : value\n );\n }\n }\n}\n\n/**\n * Normalize a rule definition.\n * @param {Function|Rule} rule The rule definition to normalize.\n * @returns {Rule} The normalized rule definition.\n */\nfunction normalizePluginRule(rule) {\n return typeof rule === \"function\" ? { create: rule } : rule;\n}\n\n/**\n * Delete the mutation methods from a given map.\n * @param {Map} map The map object to delete.\n * @returns {void}\n */\nfunction deleteMutationMethods(map) {\n Object.defineProperties(map, {\n clear: { configurable: true, value: void 0 },\n delete: { configurable: true, value: void 0 },\n set: { configurable: true, value: void 0 }\n });\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArrayElement[]} elements The config elements.\n * @param {ConfigArrayInternalSlots} slots The internal slots.\n * @returns {void}\n */\nfunction initPluginMemberMaps(elements, slots) {\n const processed = new Set();\n\n slots.envMap = new Map();\n slots.processorMap = new Map();\n slots.ruleMap = new Map();\n\n for (const element of elements) {\n if (!element.plugins) {\n continue;\n }\n\n for (const [pluginId, value] of Object.entries(element.plugins)) {\n const plugin = value.definition;\n\n if (!plugin || processed.has(pluginId)) {\n continue;\n }\n processed.add(pluginId);\n\n collect(pluginId, plugin.environments, slots.envMap);\n collect(pluginId, plugin.processors, slots.processorMap);\n collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);\n }\n }\n\n deleteMutationMethods(slots.envMap);\n deleteMutationMethods(slots.processorMap);\n deleteMutationMethods(slots.ruleMap);\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArray} instance The config elements.\n * @returns {ConfigArrayInternalSlots} The extracted config.\n */\nfunction ensurePluginMemberMaps(instance) {\n const slots = internalSlotsMap.get(instance);\n\n if (!slots.ruleMap) {\n initPluginMemberMaps(instance, slots);\n }\n\n return slots;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The Config Array.\n *\n * `ConfigArray` instance contains all settings, parsers, and plugins.\n * You need to call `ConfigArray#extractConfig(filePath)` method in order to\n * extract, merge and get only the config data which is related to an arbitrary\n * file.\n * @extends {Array}\n */\nclass ConfigArray extends Array {\n\n /**\n * Get the plugin environments.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin environments.\n */\n get pluginEnvironments() {\n return ensurePluginMemberMaps(this).envMap;\n }\n\n /**\n * Get the plugin processors.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin processors.\n */\n get pluginProcessors() {\n return ensurePluginMemberMaps(this).processorMap;\n }\n\n /**\n * Get the plugin rules.\n * The returned map cannot be mutated.\n * @returns {ReadonlyMap} The plugin rules.\n */\n get pluginRules() {\n return ensurePluginMemberMaps(this).ruleMap;\n }\n\n /**\n * Check if this config has `root` flag.\n * @returns {boolean} `true` if this config array is root.\n */\n isRoot() {\n for (let i = this.length - 1; i >= 0; --i) {\n const root = this[i].root;\n\n if (typeof root === \"boolean\") {\n return root;\n }\n }\n return false;\n }\n\n /**\n * Extract the config data which is related to a given file.\n * @param {string} filePath The absolute path to the target file.\n * @returns {ExtractedConfig} The extracted config data.\n */\n extractConfig(filePath) {\n const { cache } = internalSlotsMap.get(this);\n const indices = getMatchedIndices(this, filePath);\n const cacheKey = indices.join(\",\");\n\n if (!cache.has(cacheKey)) {\n cache.set(cacheKey, createConfig(this, indices));\n }\n\n return cache.get(cacheKey);\n }\n\n /**\n * Check if a given path is an additional lint target.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the file is an additional lint target.\n */\n isAdditionalTargetPath(filePath) {\n for (const { criteria, type } of this) {\n if (\n type === \"config\" &&\n criteria &&\n !criteria.endsWithWildcard &&\n criteria.test(filePath)\n ) {\n return true;\n }\n }\n return false;\n }\n}\n\n/**\n * Get the used extracted configs.\n * CLIEngine will use this method to collect used deprecated rules.\n * @param {ConfigArray} instance The config array object to get.\n * @returns {ExtractedConfig[]} The used extracted configs.\n * @private\n */\nfunction getUsedExtractedConfigs(instance) {\n const { cache } = internalSlotsMap.get(instance);\n\n return Array.from(cache.values());\n}\n\n\nexport {\n ConfigArray,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview `ConfigDependency` class.\n *\n * `ConfigDependency` class expresses a loaded parser or plugin.\n *\n * If the parser or plugin was loaded successfully, it has `definition` property\n * and `filePath` property. Otherwise, it has `error` property.\n *\n * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it\n * omits `definition` property.\n *\n * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers\n * or plugins.\n *\n * @author Toru Nagashima \n */\n\nimport util from \"util\";\n\n/**\n * The class is to store parsers or plugins.\n * This class hides the loaded object from `JSON.stringify()` and `console.log`.\n * @template T\n */\nclass ConfigDependency {\n\n /**\n * Initialize this instance.\n * @param {Object} data The dependency data.\n * @param {T} [data.definition] The dependency if the loading succeeded.\n * @param {Error} [data.error] The error object if the loading failed.\n * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.\n * @param {string} data.id The ID of this dependency.\n * @param {string} data.importerName The name of the config file which loads this dependency.\n * @param {string} data.importerPath The path to the config file which loads this dependency.\n */\n constructor({\n definition = null,\n error = null,\n filePath = null,\n id,\n importerName,\n importerPath\n }) {\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {T|null}\n */\n this.definition = definition;\n\n /**\n * The error object if the loading failed.\n * @type {Error|null}\n */\n this.error = error;\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {string|null}\n */\n this.filePath = filePath;\n\n /**\n * The ID of this dependency.\n * @type {string}\n */\n this.id = id;\n\n /**\n * The name of the config file which loads this dependency.\n * @type {string}\n */\n this.importerName = importerName;\n\n /**\n * The path to the config file which loads this dependency.\n * @type {string}\n */\n this.importerPath = importerPath;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n const obj = this[util.inspect.custom]();\n\n // Display `error.message` (`Error#message` is unenumerable).\n if (obj.error instanceof Error) {\n obj.error = { ...obj.error, message: obj.error.message };\n }\n\n return obj;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n const {\n definition: _ignore, // eslint-disable-line no-unused-vars\n ...obj\n } = this;\n\n return obj;\n }\n}\n\n/** @typedef {ConfigDependency} DependentParser */\n/** @typedef {ConfigDependency} DependentPlugin */\n\nexport { ConfigDependency };\n","/**\n * @fileoverview `OverrideTester` class.\n *\n * `OverrideTester` class handles `files` property and `excludedFiles` property\n * of `overrides` config.\n *\n * It provides one method.\n *\n * - `test(filePath)`\n * Test if a file path matches the pair of `files` property and\n * `excludedFiles` property. The `filePath` argument must be an absolute\n * path.\n *\n * `ConfigArrayFactory` creates `OverrideTester` objects when it processes\n * `overrides` properties.\n *\n * @author Toru Nagashima \n */\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport util from \"util\";\nimport minimatch from \"minimatch\";\n\nconst { Minimatch } = minimatch;\n\nconst minimatchOpts = { dot: true, matchBase: true };\n\n/**\n * @typedef {Object} Pattern\n * @property {InstanceType[] | null} includes The positive matchers.\n * @property {InstanceType[] | null} excludes The negative matchers.\n */\n\n/**\n * Normalize a given pattern to an array.\n * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.\n * @returns {string[]|null} Normalized patterns.\n * @private\n */\nfunction normalizePatterns(patterns) {\n if (Array.isArray(patterns)) {\n return patterns.filter(Boolean);\n }\n if (typeof patterns === \"string\" && patterns) {\n return [patterns];\n }\n return [];\n}\n\n/**\n * Create the matchers of given patterns.\n * @param {string[]} patterns The patterns.\n * @returns {InstanceType[] | null} The matchers.\n */\nfunction toMatcher(patterns) {\n if (patterns.length === 0) {\n return null;\n }\n return patterns.map(pattern => {\n if (/^\\.[/\\\\]/u.test(pattern)) {\n return new Minimatch(\n pattern.slice(2),\n\n // `./*.js` should not match with `subdir/foo.js`\n { ...minimatchOpts, matchBase: false }\n );\n }\n return new Minimatch(pattern, minimatchOpts);\n });\n}\n\n/**\n * Convert a given matcher to string.\n * @param {Pattern} matchers The matchers.\n * @returns {string} The string expression of the matcher.\n */\nfunction patternToJson({ includes, excludes }) {\n return {\n includes: includes && includes.map(m => m.pattern),\n excludes: excludes && excludes.map(m => m.pattern)\n };\n}\n\n/**\n * The class to test given paths are matched by the patterns.\n */\nclass OverrideTester {\n\n /**\n * Create a tester with given criteria.\n * If there are no criteria, returns `null`.\n * @param {string|string[]} files The glob patterns for included files.\n * @param {string|string[]} excludedFiles The glob patterns for excluded files.\n * @param {string} basePath The path to the base directory to test paths.\n * @returns {OverrideTester|null} The created instance or `null`.\n */\n static create(files, excludedFiles, basePath) {\n const includePatterns = normalizePatterns(files);\n const excludePatterns = normalizePatterns(excludedFiles);\n let endsWithWildcard = false;\n\n if (includePatterns.length === 0) {\n return null;\n }\n\n // Rejects absolute paths or relative paths to parents.\n for (const pattern of includePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n if (pattern.endsWith(\"*\")) {\n endsWithWildcard = true;\n }\n }\n for (const pattern of excludePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n }\n\n const includes = toMatcher(includePatterns);\n const excludes = toMatcher(excludePatterns);\n\n return new OverrideTester(\n [{ includes, excludes }],\n basePath,\n endsWithWildcard\n );\n }\n\n /**\n * Combine two testers by logical and.\n * If either of the testers was `null`, returns the other tester.\n * The `basePath` property of the two must be the same value.\n * @param {OverrideTester|null} a A tester.\n * @param {OverrideTester|null} b Another tester.\n * @returns {OverrideTester|null} Combined tester.\n */\n static and(a, b) {\n if (!b) {\n return a && new OverrideTester(\n a.patterns,\n a.basePath,\n a.endsWithWildcard\n );\n }\n if (!a) {\n return new OverrideTester(\n b.patterns,\n b.basePath,\n b.endsWithWildcard\n );\n }\n\n assert.strictEqual(a.basePath, b.basePath);\n return new OverrideTester(\n a.patterns.concat(b.patterns),\n a.basePath,\n a.endsWithWildcard || b.endsWithWildcard\n );\n }\n\n /**\n * Initialize this instance.\n * @param {Pattern[]} patterns The matchers.\n * @param {string} basePath The base path.\n * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.\n */\n constructor(patterns, basePath, endsWithWildcard = false) {\n\n /** @type {Pattern[]} */\n this.patterns = patterns;\n\n /** @type {string} */\n this.basePath = basePath;\n\n /** @type {boolean} */\n this.endsWithWildcard = endsWithWildcard;\n }\n\n /**\n * Test if a given path is matched or not.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the path was matched.\n */\n test(filePath) {\n if (typeof filePath !== \"string\" || !path.isAbsolute(filePath)) {\n throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);\n }\n const relativePath = path.relative(this.basePath, filePath);\n\n return this.patterns.every(({ includes, excludes }) => (\n (!includes || includes.some(m => m.match(relativePath))) &&\n (!excludes || !excludes.some(m => m.match(relativePath)))\n ));\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n if (this.patterns.length === 1) {\n return {\n ...patternToJson(this.patterns[0]),\n basePath: this.basePath\n };\n }\n return {\n AND: this.patterns.map(patternToJson),\n basePath: this.basePath\n };\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n return this.toJSON();\n }\n}\n\nexport { OverrideTester };\n","/**\n * @fileoverview `ConfigArray` class.\n * @author Toru Nagashima \n */\n\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array.js\";\nimport { ConfigDependency } from \"./config-dependency.js\";\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\nimport { OverrideTester } from \"./override-tester.js\";\n\nexport {\n ConfigArray,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview Config file operations. This file must be usable in the browser,\n * so no Node-specific code can be here.\n * @author Nicholas C. Zakas\n */\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\nconst RULE_SEVERITY_STRINGS = [\"off\", \"warn\", \"error\"],\n RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {\n map[value] = index;\n return map;\n }, {}),\n VALID_SEVERITIES = [0, 1, 2, \"off\", \"warn\", \"error\"];\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Normalizes the severity value of a rule's configuration to a number\n * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally\n * received from the user. A valid config value is either 0, 1, 2, the string \"off\" (treated the same as 0),\n * the string \"warn\" (treated the same as 1), the string \"error\" (treated the same as 2), or an array\n * whose first element is one of the above values. Strings are matched case-insensitively.\n * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.\n */\nfunction getRuleSeverity(ruleConfig) {\n const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (severityValue === 0 || severityValue === 1 || severityValue === 2) {\n return severityValue;\n }\n\n if (typeof severityValue === \"string\") {\n return RULE_SEVERITY[severityValue.toLowerCase()] || 0;\n }\n\n return 0;\n}\n\n/**\n * Converts old-style severity settings (0, 1, 2) into new-style\n * severity settings (off, warn, error) for all rules. Assumption is that severity\n * values have already been validated as correct.\n * @param {Object} config The config object to normalize.\n * @returns {void}\n */\nfunction normalizeToStrings(config) {\n\n if (config.rules) {\n Object.keys(config.rules).forEach(ruleId => {\n const ruleConfig = config.rules[ruleId];\n\n if (typeof ruleConfig === \"number\") {\n config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];\n } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === \"number\") {\n ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];\n }\n });\n }\n}\n\n/**\n * Determines if the severity for the given rule configuration represents an error.\n * @param {int|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} True if the rule represents an error, false if not.\n */\nfunction isErrorSeverity(ruleConfig) {\n return getRuleSeverity(ruleConfig) === 2;\n}\n\n/**\n * Checks whether a given config has valid severity or not.\n * @param {number|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isValidSeverity(ruleConfig) {\n let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (typeof severity === \"string\") {\n severity = severity.toLowerCase();\n }\n return VALID_SEVERITIES.indexOf(severity) !== -1;\n}\n\n/**\n * Checks whether every rule of a given config has valid severity or not.\n * @param {Object} config The configuration for rules.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isEverySeverityValid(config) {\n return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));\n}\n\n/**\n * Normalizes a value for a global in a config\n * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in\n * a global directive comment\n * @returns {(\"readable\"|\"writeable\"|\"off\")} The value normalized as a string\n * @throws Error if global value is invalid\n */\nfunction normalizeConfigGlobal(configuredValue) {\n switch (configuredValue) {\n case \"off\":\n return \"off\";\n\n case true:\n case \"true\":\n case \"writeable\":\n case \"writable\":\n return \"writable\";\n\n case null:\n case false:\n case \"false\":\n case \"readable\":\n case \"readonly\":\n return \"readonly\";\n\n default:\n throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);\n }\n}\n\nexport {\n getRuleSeverity,\n normalizeToStrings,\n isErrorSeverity,\n isValidSeverity,\n isEverySeverityValid,\n normalizeConfigGlobal\n};\n","/**\n * @fileoverview Provide the function that emits deprecation warnings.\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport path from \"path\";\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\n// Defitions for deprecation warnings.\nconst deprecationWarningMessages = {\n ESLINT_LEGACY_ECMAFEATURES:\n \"The 'ecmaFeatures' config file property is deprecated and has no effect.\",\n ESLINT_PERSONAL_CONFIG_LOAD:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please use a config file per project or the '--config' option.\",\n ESLINT_PERSONAL_CONFIG_SUPPRESS:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please remove it or add 'root:true' to the config files in your \" +\n \"projects in order to avoid loading '~/.eslintrc.*' accidentally.\"\n};\n\nconst sourceFileErrorCache = new Set();\n\n/**\n * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted\n * for each unique file path, but repeated invocations with the same file path have no effect.\n * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.\n * @param {string} source The name of the configuration source to report the warning for.\n * @param {string} errorCode The warning message to show.\n * @returns {void}\n */\nfunction emitDeprecationWarning(source, errorCode) {\n const cacheKey = JSON.stringify({ source, errorCode });\n\n if (sourceFileErrorCache.has(cacheKey)) {\n return;\n }\n sourceFileErrorCache.add(cacheKey);\n\n const rel = path.relative(process.cwd(), source);\n const message = deprecationWarningMessages[errorCode];\n\n process.emitWarning(\n `${message} (found in \"${rel}\")`,\n \"DeprecationWarning\",\n errorCode\n );\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n emitDeprecationWarning\n};\n","/**\n * @fileoverview The instance of Ajv validator.\n * @author Evgeny Poberezkin\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport Ajv from \"ajv\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/*\n * Copied from ajv/lib/refs/json-schema-draft-04.json\n * The MIT License (MIT)\n * Copyright (c) 2015-2017 Evgeny Poberezkin\n */\nconst metaSchema = {\n id: \"http://json-schema.org/draft-04/schema#\",\n $schema: \"http://json-schema.org/draft-04/schema#\",\n description: \"Core schema meta-schema\",\n definitions: {\n schemaArray: {\n type: \"array\",\n minItems: 1,\n items: { $ref: \"#\" }\n },\n positiveInteger: {\n type: \"integer\",\n minimum: 0\n },\n positiveIntegerDefault0: {\n allOf: [{ $ref: \"#/definitions/positiveInteger\" }, { default: 0 }]\n },\n simpleTypes: {\n enum: [\"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\"]\n },\n stringArray: {\n type: \"array\",\n items: { type: \"string\" },\n minItems: 1,\n uniqueItems: true\n }\n },\n type: \"object\",\n properties: {\n id: {\n type: \"string\"\n },\n $schema: {\n type: \"string\"\n },\n title: {\n type: \"string\"\n },\n description: {\n type: \"string\"\n },\n default: { },\n multipleOf: {\n type: \"number\",\n minimum: 0,\n exclusiveMinimum: true\n },\n maximum: {\n type: \"number\"\n },\n exclusiveMaximum: {\n type: \"boolean\",\n default: false\n },\n minimum: {\n type: \"number\"\n },\n exclusiveMinimum: {\n type: \"boolean\",\n default: false\n },\n maxLength: { $ref: \"#/definitions/positiveInteger\" },\n minLength: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n pattern: {\n type: \"string\",\n format: \"regex\"\n },\n additionalItems: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n items: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/schemaArray\" }\n ],\n default: { }\n },\n maxItems: { $ref: \"#/definitions/positiveInteger\" },\n minItems: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n uniqueItems: {\n type: \"boolean\",\n default: false\n },\n maxProperties: { $ref: \"#/definitions/positiveInteger\" },\n minProperties: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n required: { $ref: \"#/definitions/stringArray\" },\n additionalProperties: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n definitions: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n properties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n patternProperties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n dependencies: {\n type: \"object\",\n additionalProperties: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/stringArray\" }\n ]\n }\n },\n enum: {\n type: \"array\",\n minItems: 1,\n uniqueItems: true\n },\n type: {\n anyOf: [\n { $ref: \"#/definitions/simpleTypes\" },\n {\n type: \"array\",\n items: { $ref: \"#/definitions/simpleTypes\" },\n minItems: 1,\n uniqueItems: true\n }\n ]\n },\n format: { type: \"string\" },\n allOf: { $ref: \"#/definitions/schemaArray\" },\n anyOf: { $ref: \"#/definitions/schemaArray\" },\n oneOf: { $ref: \"#/definitions/schemaArray\" },\n not: { $ref: \"#\" }\n },\n dependencies: {\n exclusiveMaximum: [\"maximum\"],\n exclusiveMinimum: [\"minimum\"]\n },\n default: { }\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport default (additionalOptions = {}) => {\n const ajv = new Ajv({\n meta: false,\n useDefaults: true,\n validateSchema: false,\n missingRefs: \"ignore\",\n verbose: true,\n schemaId: \"auto\",\n ...additionalOptions\n });\n\n ajv.addMetaSchema(metaSchema);\n // eslint-disable-next-line no-underscore-dangle\n ajv._opts.defaultMeta = metaSchema.id;\n\n return ajv;\n};\n","/**\n * @fileoverview Defines a schema for configs.\n * @author Sylvan Mably\n */\n\nconst baseConfigProperties = {\n $schema: { type: \"string\" },\n env: { type: \"object\" },\n extends: { $ref: \"#/definitions/stringOrStrings\" },\n globals: { type: \"object\" },\n overrides: {\n type: \"array\",\n items: { $ref: \"#/definitions/overrideConfig\" },\n additionalItems: false\n },\n parser: { type: [\"string\", \"null\"] },\n parserOptions: { type: \"object\" },\n plugins: { type: \"array\" },\n processor: { type: \"string\" },\n rules: { type: \"object\" },\n settings: { type: \"object\" },\n noInlineConfig: { type: \"boolean\" },\n reportUnusedDisableDirectives: { type: \"boolean\" },\n\n ecmaFeatures: { type: \"object\" } // deprecated; logs a warning when used\n};\n\nconst configSchema = {\n definitions: {\n stringOrStrings: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false\n }\n ]\n },\n stringOrStringsRequired: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false,\n minItems: 1\n }\n ]\n },\n\n // Config at top-level.\n objectConfig: {\n type: \"object\",\n properties: {\n root: { type: \"boolean\" },\n ignorePatterns: { $ref: \"#/definitions/stringOrStrings\" },\n ...baseConfigProperties\n },\n additionalProperties: false\n },\n\n // Config in `overrides`.\n overrideConfig: {\n type: \"object\",\n properties: {\n excludedFiles: { $ref: \"#/definitions/stringOrStrings\" },\n files: { $ref: \"#/definitions/stringOrStringsRequired\" },\n ...baseConfigProperties\n },\n required: [\"files\"],\n additionalProperties: false\n }\n },\n\n $ref: \"#/definitions/objectConfig\"\n};\n\nexport default configSchema;\n","/**\n * @fileoverview Defines environment settings and globals.\n * @author Elan Shanker\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport globals from \"globals\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the object that has difference.\n * @param {Record} current The newer object.\n * @param {Record} prev The older object.\n * @returns {Record} The difference object.\n */\nfunction getDiff(current, prev) {\n const retv = {};\n\n for (const [key, value] of Object.entries(current)) {\n if (!Object.hasOwnProperty.call(prev, key)) {\n retv[key] = value;\n }\n }\n\n return retv;\n}\n\nconst newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...\nconst newGlobals2017 = {\n Atomics: false,\n SharedArrayBuffer: false\n};\nconst newGlobals2020 = {\n BigInt: false,\n BigInt64Array: false,\n BigUint64Array: false,\n globalThis: false\n};\n\nconst newGlobals2021 = {\n AggregateError: false,\n FinalizationRegistry: false,\n WeakRef: false\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/** @type {Map} */\nexport default new Map(Object.entries({\n\n // Language\n builtin: {\n globals: globals.es5\n },\n es6: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2015: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2016: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 7\n }\n },\n es2017: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 8\n }\n },\n es2018: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 9\n }\n },\n es2019: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 10\n }\n },\n es2020: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },\n parserOptions: {\n ecmaVersion: 11\n }\n },\n es2021: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 12\n }\n },\n es2022: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 13\n }\n },\n\n // Platforms\n browser: {\n globals: globals.browser\n },\n node: {\n globals: globals.node,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n \"shared-node-browser\": {\n globals: globals[\"shared-node-browser\"]\n },\n worker: {\n globals: globals.worker\n },\n serviceworker: {\n globals: globals.serviceworker\n },\n\n // Frameworks\n commonjs: {\n globals: globals.commonjs,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n amd: {\n globals: globals.amd\n },\n mocha: {\n globals: globals.mocha\n },\n jasmine: {\n globals: globals.jasmine\n },\n jest: {\n globals: globals.jest\n },\n phantomjs: {\n globals: globals.phantomjs\n },\n jquery: {\n globals: globals.jquery\n },\n qunit: {\n globals: globals.qunit\n },\n prototypejs: {\n globals: globals.prototypejs\n },\n shelljs: {\n globals: globals.shelljs\n },\n meteor: {\n globals: globals.meteor\n },\n mongo: {\n globals: globals.mongo\n },\n protractor: {\n globals: globals.protractor\n },\n applescript: {\n globals: globals.applescript\n },\n nashorn: {\n globals: globals.nashorn\n },\n atomtest: {\n globals: globals.atomtest\n },\n embertest: {\n globals: globals.embertest\n },\n webextensions: {\n globals: globals.webextensions\n },\n greasemonkey: {\n globals: globals.greasemonkey\n }\n}));\n","/**\n * @fileoverview Validates configs.\n * @author Brandon Mills\n */\n\n/* eslint class-methods-use-this: \"off\" */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport util from \"util\";\nimport * as ConfigOps from \"./config-ops.js\";\nimport { emitDeprecationWarning } from \"./deprecation-warnings.js\";\nimport ajvOrig from \"./ajv.js\";\nimport configSchema from \"../../conf/config-schema.js\";\nimport BuiltInEnvironments from \"../../conf/environments.js\";\n\nconst ajv = ajvOrig();\n\nconst ruleValidators = new WeakMap();\nconst noop = Function.prototype;\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\nlet validateSchema;\nconst severityMap = {\n error: 2,\n warn: 1,\n off: 0\n};\n\nconst validated = new WeakSet();\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nexport default class ConfigValidator {\n constructor({ builtInRules = new Map() } = {}) {\n this.builtInRules = builtInRules;\n }\n\n /**\n * Gets a complete options schema for a rule.\n * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object\n * @returns {Object} JSON Schema for the rule's options.\n */\n getRuleOptionsSchema(rule) {\n if (!rule) {\n return null;\n }\n\n const schema = rule.schema || rule.meta && rule.meta.schema;\n\n // Given a tuple of schemas, insert warning level at the beginning\n if (Array.isArray(schema)) {\n if (schema.length) {\n return {\n type: \"array\",\n items: schema,\n minItems: 0,\n maxItems: schema.length\n };\n }\n return {\n type: \"array\",\n minItems: 0,\n maxItems: 0\n };\n\n }\n\n // Given a full schema, leave it alone\n return schema || null;\n }\n\n /**\n * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.\n * @param {options} options The given options for the rule.\n * @returns {number|string} The rule's severity value\n */\n validateRuleSeverity(options) {\n const severity = Array.isArray(options) ? options[0] : options;\n const normSeverity = typeof severity === \"string\" ? severityMap[severity.toLowerCase()] : severity;\n\n if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {\n return normSeverity;\n }\n\n throw new Error(`\\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, \"\\\"\").replace(/\\n/gu, \"\")}').\\n`);\n\n }\n\n /**\n * Validates the non-severity options passed to a rule, based on its schema.\n * @param {{create: Function}} rule The rule to validate\n * @param {Array} localOptions The options for the rule, excluding severity\n * @returns {void}\n */\n validateRuleSchema(rule, localOptions) {\n if (!ruleValidators.has(rule)) {\n const schema = this.getRuleOptionsSchema(rule);\n\n if (schema) {\n ruleValidators.set(rule, ajv.compile(schema));\n }\n }\n\n const validateRule = ruleValidators.get(rule);\n\n if (validateRule) {\n validateRule(localOptions);\n if (validateRule.errors) {\n throw new Error(validateRule.errors.map(\n error => `\\tValue ${JSON.stringify(error.data)} ${error.message}.\\n`\n ).join(\"\"));\n }\n }\n }\n\n /**\n * Validates a rule's options against its schema.\n * @param {{create: Function}|null} rule The rule that the config is being validated for\n * @param {string} ruleId The rule's unique name.\n * @param {Array|number} options The given options for the rule.\n * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,\n * no source is prepended to the message.\n * @returns {void}\n */\n validateRuleOptions(rule, ruleId, options, source = null) {\n try {\n const severity = this.validateRuleSeverity(options);\n\n if (severity !== 0) {\n this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);\n }\n } catch (err) {\n const enhancedMessage = `Configuration for rule \"${ruleId}\" is invalid:\\n${err.message}`;\n\n if (typeof source === \"string\") {\n throw new Error(`${source}:\\n\\t${enhancedMessage}`);\n } else {\n throw new Error(enhancedMessage);\n }\n }\n }\n\n /**\n * Validates an environment object\n * @param {Object} environment The environment config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.\n * @returns {void}\n */\n validateEnvironment(\n environment,\n source,\n getAdditionalEnv = noop\n ) {\n\n // not having an environment is ok\n if (!environment) {\n return;\n }\n\n Object.keys(environment).forEach(id => {\n const env = getAdditionalEnv(id) || BuiltInEnvironments.get(id) || null;\n\n if (!env) {\n const message = `${source}:\\n\\tEnvironment key \"${id}\" is unknown\\n`;\n\n throw new Error(message);\n }\n });\n }\n\n /**\n * Validates a rules config object\n * @param {Object} rulesConfig The rules config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules\n * @returns {void}\n */\n validateRules(\n rulesConfig,\n source,\n getAdditionalRule = noop\n ) {\n if (!rulesConfig) {\n return;\n }\n\n Object.keys(rulesConfig).forEach(id => {\n const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;\n\n this.validateRuleOptions(rule, id, rulesConfig[id], source);\n });\n }\n\n /**\n * Validates a `globals` section of a config file\n * @param {Object} globalsConfig The `globals` section\n * @param {string|null} source The name of the configuration source to report in the event of an error.\n * @returns {void}\n */\n validateGlobals(globalsConfig, source = null) {\n if (!globalsConfig) {\n return;\n }\n\n Object.entries(globalsConfig)\n .forEach(([configuredGlobal, configuredValue]) => {\n try {\n ConfigOps.normalizeConfigGlobal(configuredValue);\n } catch (err) {\n throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\\n${err.message}`);\n }\n });\n }\n\n /**\n * Validate `processor` configuration.\n * @param {string|undefined} processorName The processor name.\n * @param {string} source The name of config file.\n * @param {function(id:string): Processor} getProcessor The getter of defined processors.\n * @returns {void}\n */\n validateProcessor(processorName, source, getProcessor) {\n if (processorName && !getProcessor(processorName)) {\n throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);\n }\n }\n\n /**\n * Formats an array of schema validation errors.\n * @param {Array} errors An array of error messages to format.\n * @returns {string} Formatted error message\n */\n formatErrors(errors) {\n return errors.map(error => {\n if (error.keyword === \"additionalProperties\") {\n const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;\n\n return `Unexpected top-level property \"${formattedPropertyPath}\"`;\n }\n if (error.keyword === \"type\") {\n const formattedField = error.dataPath.slice(1);\n const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join(\"/\") : error.schema;\n const formattedValue = JSON.stringify(error.data);\n\n return `Property \"${formattedField}\" is the wrong type (expected ${formattedExpectedType} but got \\`${formattedValue}\\`)`;\n }\n\n const field = error.dataPath[0] === \".\" ? error.dataPath.slice(1) : error.dataPath;\n\n return `\"${field}\" ${error.message}. Value: ${JSON.stringify(error.data)}`;\n }).map(message => `\\t- ${message}.\\n`).join(\"\");\n }\n\n /**\n * Validates the top level properties of the config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @returns {void}\n */\n validateConfigSchema(config, source = null) {\n validateSchema = validateSchema || ajv.compile(configSchema);\n\n if (!validateSchema(config)) {\n throw new Error(`ESLint configuration in ${source} is invalid:\\n${this.formatErrors(validateSchema.errors)}`);\n }\n\n if (Object.hasOwnProperty.call(config, \"ecmaFeatures\")) {\n emitDeprecationWarning(source, \"ESLINT_LEGACY_ECMAFEATURES\");\n }\n }\n\n /**\n * Validates an entire config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.\n * @returns {void}\n */\n validate(config, source, getAdditionalRule, getAdditionalEnv) {\n this.validateConfigSchema(config, source);\n this.validateRules(config.rules, source, getAdditionalRule);\n this.validateEnvironment(config.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n\n for (const override of config.overrides || []) {\n this.validateRules(override.rules, source, getAdditionalRule);\n this.validateEnvironment(override.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n }\n }\n\n /**\n * Validate config array object.\n * @param {ConfigArray} configArray The config array to validate.\n * @returns {void}\n */\n validateConfigArray(configArray) {\n const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);\n const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);\n const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);\n\n // Validate.\n for (const element of configArray) {\n if (validated.has(element)) {\n continue;\n }\n validated.add(element);\n\n this.validateEnvironment(element.env, element.name, getPluginEnv);\n this.validateGlobals(element.globals, element.name);\n this.validateProcessor(element.processor, element.name, getPluginProcessor);\n this.validateRules(element.rules, element.name, getPluginRule);\n }\n }\n\n}\n","/**\n * @fileoverview Common helpers for naming of plugins, formatters and configs\n */\n\nconst NAMESPACE_REGEX = /^@.*\\//iu;\n\n/**\n * Brings package name to correct format based on prefix\n * @param {string} name The name of the package.\n * @param {string} prefix Can be either \"eslint-plugin\", \"eslint-config\" or \"eslint-formatter\"\n * @returns {string} Normalized name of the package\n * @private\n */\nfunction normalizePackageName(name, prefix) {\n let normalizedName = name;\n\n /**\n * On Windows, name can come in with Windows slashes instead of Unix slashes.\n * Normalize to Unix first to avoid errors later on.\n * https://github.com/eslint/eslint/issues/5644\n */\n if (normalizedName.includes(\"\\\\\")) {\n normalizedName = normalizedName.replace(/\\\\/gu, \"/\");\n }\n\n if (normalizedName.charAt(0) === \"@\") {\n\n /**\n * it's a scoped package\n * package name is the prefix, or just a username\n */\n const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, \"u\"),\n scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, \"u\");\n\n if (scopedPackageShortcutRegex.test(normalizedName)) {\n normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);\n } else if (!scopedPackageNameRegex.test(normalizedName.split(\"/\")[1])) {\n\n /**\n * for scoped packages, insert the prefix after the first / unless\n * the path is already @scope/eslint or @scope/eslint-xxx-yyy\n */\n normalizedName = normalizedName.replace(/^@([^/]+)\\/(.*)$/u, `@$1/${prefix}-$2`);\n }\n } else if (!normalizedName.startsWith(`${prefix}-`)) {\n normalizedName = `${prefix}-${normalizedName}`;\n }\n\n return normalizedName;\n}\n\n/**\n * Removes the prefix from a fullname.\n * @param {string} fullname The term which may have the prefix.\n * @param {string} prefix The prefix to remove.\n * @returns {string} The term without prefix.\n */\nfunction getShorthandName(fullname, prefix) {\n if (fullname[0] === \"@\") {\n let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, \"u\").exec(fullname);\n\n if (matchResult) {\n return matchResult[1];\n }\n\n matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, \"u\").exec(fullname);\n if (matchResult) {\n return `${matchResult[1]}/${matchResult[2]}`;\n }\n } else if (fullname.startsWith(`${prefix}-`)) {\n return fullname.slice(prefix.length + 1);\n }\n\n return fullname;\n}\n\n/**\n * Gets the scope (namespace) of a term.\n * @param {string} term The term which may have the namespace.\n * @returns {string} The namespace of the term if it has one.\n */\nfunction getNamespaceFromTerm(term) {\n const match = term.match(NAMESPACE_REGEX);\n\n return match ? match[0] : \"\";\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n normalizePackageName,\n getShorthandName,\n getNamespaceFromTerm\n};\n","/**\n * Utility for resolving a module relative to another module\n * @author Teddy Katz\n */\n\nimport Module from \"module\";\n\n/*\n * `Module.createRequire` is added in v12.2.0. It supports URL as well.\n * We only support the case where the argument is a filepath, not a URL.\n */\nconst createRequire = Module.createRequire;\n\n/**\n * Resolves a Node module relative to another module\n * @param {string} moduleName The name of a Node module, or a path to a Node module.\n * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be\n * a file rather than a directory, but the file need not actually exist.\n * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`\n */\nfunction resolve(moduleName, relativeToPath) {\n try {\n return createRequire(relativeToPath).resolve(moduleName);\n } catch (error) {\n\n // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.\n if (\n typeof error === \"object\" &&\n error !== null &&\n error.code === \"MODULE_NOT_FOUND\" &&\n !error.requireStack &&\n error.message.includes(moduleName)\n ) {\n error.message += `\\nRequire stack:\\n- ${relativeToPath}`;\n }\n throw error;\n }\n}\n\nexport {\n resolve\n};\n","/**\n * @fileoverview The factory of `ConfigArray` objects.\n *\n * This class provides methods to create `ConfigArray` instance.\n *\n * - `create(configData, options)`\n * Create a `ConfigArray` instance from a config data. This is to handle CLI\n * options except `--config`.\n * - `loadFile(filePath, options)`\n * Create a `ConfigArray` instance from a config file. This is to handle\n * `--config` option. If the file was not found, throws the following error:\n * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.\n * - If the filename was `package.json`, an IO error or an\n * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.\n * - Otherwise, an IO error such as `ENOENT`.\n * - `loadInDirectory(directoryPath, options)`\n * Create a `ConfigArray` instance from a config file which is on a given\n * directory. This tries to load `.eslintrc.*` or `package.json`. If not\n * found, returns an empty `ConfigArray`.\n * - `loadESLintIgnore(filePath)`\n * Create a `ConfigArray` instance from a config file that is `.eslintignore`\n * format. This is to handle `--ignore-path` option.\n * - `loadDefaultESLintIgnore()`\n * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in\n * the current working directory.\n *\n * `ConfigArrayFactory` class has the responsibility that loads configuration\n * files, including loading `extends`, `parser`, and `plugins`. The created\n * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.\n *\n * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class\n * handles cascading and hierarchy.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport fs from \"fs\";\nimport { createRequire } from \"module\";\nimport path from \"path\";\nimport stripComments from \"strip-json-comments\";\n\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern,\n OverrideTester\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\n\nconst require = createRequire(import.meta.url);\n\nconst debug = debugOrig(\"eslintrc:config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\nconst configFilenames = [\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \".eslintrc.json\",\n \".eslintrc\",\n \"package.json\"\n];\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").OverrideConfigData} OverrideConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {import(\"./config-array/config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-array/config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {ConfigArray[0]} ConfigArrayElement */\n\n/**\n * @typedef {Object} ConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {string} [cwd] The path to the current working directory.\n * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryInternalSlots\n * @property {Map} additionalPluginPool The map for additional plugins.\n * @property {string} cwd The path to the current working directory.\n * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {string} pluginBasePath The base path to resolve plugins.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Check if a given string is a file path.\n * @param {string} nameOrPath A module name or file path.\n * @returns {boolean} `true` if the `nameOrPath` is a file path.\n */\nfunction isFilePath(nameOrPath) {\n return (\n /^\\.{1,2}[/\\\\]/u.test(nameOrPath) ||\n path.isAbsolute(nameOrPath)\n );\n}\n\n/**\n * Convenience wrapper for synchronously reading file contents.\n * @param {string} filePath The filename to read.\n * @returns {string} The file contents, with the BOM removed.\n * @private\n */\nfunction readFile(filePath) {\n return fs.readFileSync(filePath, \"utf8\").replace(/^\\ufeff/u, \"\");\n}\n\n/**\n * Loads a YAML configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadYAMLConfigFile(filePath) {\n debug(`Loading YAML config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n\n // empty YAML file can be null, so always use\n return yaml.load(readFile(filePath)) || {};\n } catch (e) {\n debug(`Error reading YAML file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JSON configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSONConfigFile(filePath) {\n debug(`Loading JSON config file: ${filePath}`);\n\n try {\n return JSON.parse(stripComments(readFile(filePath)));\n } catch (e) {\n debug(`Error reading JSON file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n e.messageTemplate = \"failed-to-read-json\";\n e.messageData = {\n path: filePath,\n message: e.message\n };\n throw e;\n }\n}\n\n/**\n * Loads a legacy (.eslintrc) configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadLegacyConfigFile(filePath) {\n debug(`Loading legacy config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n return yaml.load(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};\n } catch (e) {\n debug(\"Error reading YAML file: %s\\n%o\", filePath, e);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JavaScript configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSConfigFile(filePath) {\n debug(`Loading JS config file: ${filePath}`);\n try {\n return require(filePath);\n } catch (e) {\n debug(`Error reading JavaScript file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a configuration from a package.json file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadPackageJSONConfigFile(filePath) {\n debug(`Loading package.json config file: ${filePath}`);\n try {\n const packageData = loadJSONConfigFile(filePath);\n\n if (!Object.hasOwnProperty.call(packageData, \"eslintConfig\")) {\n throw Object.assign(\n new Error(\"package.json file doesn't have 'eslintConfig' field.\"),\n { code: \"ESLINT_CONFIG_FIELD_NOT_FOUND\" }\n );\n }\n\n return packageData.eslintConfig;\n } catch (e) {\n debug(`Error reading package.json file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a `.eslintignore` from a file.\n * @param {string} filePath The filename to load.\n * @returns {string[]} The ignore patterns from the file.\n * @private\n */\nfunction loadESLintIgnoreFile(filePath) {\n debug(`Loading .eslintignore file: ${filePath}`);\n\n try {\n return readFile(filePath)\n .split(/\\r?\\n/gu)\n .filter(line => line.trim() !== \"\" && !line.startsWith(\"#\"));\n } catch (e) {\n debug(`Error reading .eslintignore file: ${filePath}`);\n e.message = `Cannot read .eslintignore file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Creates an error to notify about a missing config to extend from.\n * @param {string} configName The name of the missing config.\n * @param {string} importerName The name of the config that imported the missing config\n * @param {string} messageTemplate The text template to source error strings from.\n * @returns {Error} The error object to throw\n * @private\n */\nfunction configInvalidError(configName, importerName, messageTemplate) {\n return Object.assign(\n new Error(`Failed to load config \"${configName}\" to extend from.`),\n {\n messageTemplate,\n messageData: { configName, importerName }\n }\n );\n}\n\n/**\n * Loads a configuration file regardless of the source. Inspects the file path\n * to determine the correctly way to load the config file.\n * @param {string} filePath The path to the configuration.\n * @returns {ConfigData|null} The configuration information.\n * @private\n */\nfunction loadConfigFile(filePath) {\n switch (path.extname(filePath)) {\n case \".js\":\n case \".cjs\":\n return loadJSConfigFile(filePath);\n\n case \".json\":\n if (path.basename(filePath) === \"package.json\") {\n return loadPackageJSONConfigFile(filePath);\n }\n return loadJSONConfigFile(filePath);\n\n case \".yaml\":\n case \".yml\":\n return loadYAMLConfigFile(filePath);\n\n default:\n return loadLegacyConfigFile(filePath);\n }\n}\n\n/**\n * Write debug log.\n * @param {string} request The requested module name.\n * @param {string} relativeTo The file path to resolve the request relative to.\n * @param {string} filePath The resolved file path.\n * @returns {void}\n */\nfunction writeDebugLogForLoading(request, relativeTo, filePath) {\n /* istanbul ignore next */\n if (debug.enabled) {\n let nameAndVersion = null;\n\n try {\n const packageJsonPath = ModuleResolver.resolve(\n `${request}/package.json`,\n relativeTo\n );\n const { version = \"unknown\" } = require(packageJsonPath);\n\n nameAndVersion = `${request}@${version}`;\n } catch (error) {\n debug(\"package.json was not found:\", error.message);\n nameAndVersion = request;\n }\n\n debug(\"Loaded: %s (%s)\", nameAndVersion, filePath);\n }\n}\n\n/**\n * Create a new context with default values.\n * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.\n * @param {\"config\" | \"ignore\" | \"implicit-processor\" | undefined} providedType The type of the current configuration. Default is `\"config\"`.\n * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.\n * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.\n * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.\n * @returns {ConfigArrayFactoryLoadingContext} The created context.\n */\nfunction createContext(\n { cwd, resolvePluginsRelativeTo },\n providedType,\n providedName,\n providedFilePath,\n providedMatchBasePath\n) {\n const filePath = providedFilePath\n ? path.resolve(cwd, providedFilePath)\n : \"\";\n const matchBasePath =\n (providedMatchBasePath && path.resolve(cwd, providedMatchBasePath)) ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const name =\n providedName ||\n (filePath && path.relative(cwd, filePath)) ||\n \"\";\n const pluginBasePath =\n resolvePluginsRelativeTo ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const type = providedType || \"config\";\n\n return { filePath, matchBasePath, name, pluginBasePath, type };\n}\n\n/**\n * Normalize a given plugin.\n * - Ensure the object to have four properties: configs, environments, processors, and rules.\n * - Ensure the object to not have other properties.\n * @param {Plugin} plugin The plugin to normalize.\n * @returns {Plugin} The normalized plugin.\n */\nfunction normalizePlugin(plugin) {\n return {\n configs: plugin.configs || {},\n environments: plugin.environments || {},\n processors: plugin.processors || {},\n rules: plugin.rules || {}\n };\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The factory of `ConfigArray` objects.\n */\nclass ConfigArrayFactory {\n\n /**\n * Initialize this instance.\n * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.\n */\n constructor({\n additionalPluginPool = new Map(),\n cwd = process.cwd(),\n resolvePluginsRelativeTo,\n builtInRules,\n resolver = ModuleResolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = {}) {\n internalSlotsMap.set(this, {\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo:\n resolvePluginsRelativeTo &&\n path.resolve(cwd, resolvePluginsRelativeTo),\n builtInRules,\n resolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n });\n }\n\n /**\n * Create `ConfigArray` instance from a config data.\n * @param {ConfigData|null} configData The config data to create.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.filePath] The path to this config data.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n create(configData, { basePath, filePath, name } = {}) {\n if (!configData) {\n return new ConfigArray();\n }\n\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n const elements = this._normalizeConfigData(configData, ctx);\n\n return new ConfigArray(...elements);\n }\n\n /**\n * Load a config file.\n * @param {string} filePath The path to a config file.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n loadFile(filePath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n\n return new ConfigArray(...this._loadConfigData(ctx));\n }\n\n /**\n * Load the config file on a given directory if exists.\n * @param {string} directoryPath The path to a directory.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadInDirectory(directoryPath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n\n for (const filename of configFilenames) {\n const ctx = createContext(\n slots,\n \"config\",\n name,\n path.join(directoryPath, filename),\n basePath\n );\n\n if (fs.existsSync(ctx.filePath) && fs.statSync(ctx.filePath).isFile()) {\n let configData;\n\n try {\n configData = loadConfigFile(ctx.filePath);\n } catch (error) {\n if (!error || error.code !== \"ESLINT_CONFIG_FIELD_NOT_FOUND\") {\n throw error;\n }\n }\n\n if (configData) {\n debug(`Config file found: ${ctx.filePath}`);\n return new ConfigArray(\n ...this._normalizeConfigData(configData, ctx)\n );\n }\n }\n }\n\n debug(`Config file not found on ${directoryPath}`);\n return new ConfigArray();\n }\n\n /**\n * Check if a config file on a given directory exists or not.\n * @param {string} directoryPath The path to a directory.\n * @returns {string | null} The path to the found config file. If not found then null.\n */\n static getPathToConfigFileInDirectory(directoryPath) {\n for (const filename of configFilenames) {\n const filePath = path.join(directoryPath, filename);\n\n if (fs.existsSync(filePath)) {\n if (filename === \"package.json\") {\n try {\n loadPackageJSONConfigFile(filePath);\n return filePath;\n } catch { /* ignore */ }\n } else {\n return filePath;\n }\n }\n }\n return null;\n }\n\n /**\n * Load `.eslintignore` file.\n * @param {string} filePath The path to a `.eslintignore` file to load.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadESLintIgnore(filePath) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(\n slots,\n \"ignore\",\n void 0,\n filePath,\n slots.cwd\n );\n const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)\n );\n }\n\n /**\n * Load `.eslintignore` file in the current working directory.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadDefaultESLintIgnore() {\n const slots = internalSlotsMap.get(this);\n const eslintIgnorePath = path.resolve(slots.cwd, \".eslintignore\");\n const packageJsonPath = path.resolve(slots.cwd, \"package.json\");\n\n if (fs.existsSync(eslintIgnorePath)) {\n return this.loadESLintIgnore(eslintIgnorePath);\n }\n if (fs.existsSync(packageJsonPath)) {\n const data = loadJSONConfigFile(packageJsonPath);\n\n if (Object.hasOwnProperty.call(data, \"eslintIgnore\")) {\n if (!Array.isArray(data.eslintIgnore)) {\n throw new Error(\"Package.json eslintIgnore property requires an array of paths\");\n }\n const ctx = createContext(\n slots,\n \"ignore\",\n \"eslintIgnore in package.json\",\n packageJsonPath,\n slots.cwd\n );\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)\n );\n }\n }\n\n return new ConfigArray();\n }\n\n /**\n * Load a given config file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} Loaded config.\n * @private\n */\n _loadConfigData(ctx) {\n return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);\n }\n\n /**\n * Normalize a given `.eslintignore` data to config array elements.\n * @param {string[]} ignorePatterns The patterns to ignore files.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeESLintIgnoreData(ignorePatterns, ctx) {\n const elements = this._normalizeObjectConfigData(\n { ignorePatterns },\n ctx\n );\n\n // Set `ignorePattern.loose` flag for backward compatibility.\n for (const element of elements) {\n if (element.ignorePattern) {\n element.ignorePattern.loose = true;\n }\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _normalizeConfigData(configData, ctx) {\n const validator = new ConfigValidator();\n\n validator.validateConfigSchema(configData, ctx.name || ctx.filePath);\n return this._normalizeObjectConfigData(configData, ctx);\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData|OverrideConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigData(configData, ctx) {\n const { files, excludedFiles, ...configBody } = configData;\n const criteria = OverrideTester.create(\n files,\n excludedFiles,\n ctx.matchBasePath\n );\n const elements = this._normalizeObjectConfigDataBody(configBody, ctx);\n\n // Apply the criteria to every element.\n for (const element of elements) {\n\n /*\n * Merge the criteria.\n * This is for the `overrides` entries that came from the\n * configurations of `overrides[].extends`.\n */\n element.criteria = OverrideTester.and(criteria, element.criteria);\n\n /*\n * Remove `root` property to ignore `root` settings which came from\n * `extends` in `overrides`.\n */\n if (element.criteria) {\n element.root = void 0;\n }\n\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigDataBody(\n {\n env,\n extends: extend,\n globals,\n ignorePatterns,\n noInlineConfig,\n parser: parserName,\n parserOptions,\n plugins: pluginList,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings,\n overrides: overrideList = []\n },\n ctx\n ) {\n const extendList = Array.isArray(extend) ? extend : [extend];\n const ignorePattern = ignorePatterns && new IgnorePattern(\n Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],\n ctx.matchBasePath\n );\n\n // Flatten `extends`.\n for (const extendName of extendList.filter(Boolean)) {\n yield* this._loadExtends(extendName, ctx);\n }\n\n // Load parser & plugins.\n const parser = parserName && this._loadParser(parserName, ctx);\n const plugins = pluginList && this._loadPlugins(pluginList, ctx);\n\n // Yield pseudo config data for file extension processors.\n if (plugins) {\n yield* this._takeFileExtensionProcessors(plugins, ctx);\n }\n\n // Yield the config data except `extends` and `overrides`.\n yield {\n\n // Debug information.\n type: ctx.type,\n name: ctx.name,\n filePath: ctx.filePath,\n\n // Config data.\n criteria: null,\n env,\n globals,\n ignorePattern,\n noInlineConfig,\n parser,\n parserOptions,\n plugins,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings\n };\n\n // Flatten `overries`.\n for (let i = 0; i < overrideList.length; ++i) {\n yield* this._normalizeObjectConfigData(\n overrideList[i],\n { ...ctx, name: `${ctx.name}#overrides[${i}]` }\n );\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtends(extendName, ctx) {\n debug(\"Loading {extends:%j} relative to %s\", extendName, ctx.filePath);\n try {\n if (extendName.startsWith(\"eslint:\")) {\n return this._loadExtendedBuiltInConfig(extendName, ctx);\n }\n if (extendName.startsWith(\"plugin:\")) {\n return this._loadExtendedPluginConfig(extendName, ctx);\n }\n return this._loadExtendedShareableConfig(extendName, ctx);\n } catch (error) {\n error.message += `\\nReferenced from: ${ctx.filePath || ctx.name}`;\n throw error;\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedBuiltInConfig(extendName, ctx) {\n const {\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = internalSlotsMap.get(this);\n\n if (extendName === \"eslint:recommended\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintRecommendedConfig) {\n if (typeof getEslintRecommendedConfig !== \"function\") {\n throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);\n }\n return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintRecommendedPath\n });\n }\n if (extendName === \"eslint:all\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintAllConfig) {\n if (typeof getEslintAllConfig !== \"function\") {\n throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);\n }\n return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintAllPath\n });\n }\n\n throw configInvalidError(extendName, ctx.name, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedPluginConfig(extendName, ctx) {\n const slashIndex = extendName.lastIndexOf(\"/\");\n\n if (slashIndex === -1) {\n throw configInvalidError(extendName, ctx.filePath, \"plugin-invalid\");\n }\n\n const pluginName = extendName.slice(\"plugin:\".length, slashIndex);\n const configName = extendName.slice(slashIndex + 1);\n\n if (isFilePath(pluginName)) {\n throw new Error(\"'extends' cannot use a file path for plugins.\");\n }\n\n const plugin = this._loadPlugin(pluginName, ctx);\n const configData =\n plugin.definition &&\n plugin.definition.configs[configName];\n\n if (configData) {\n return this._normalizeConfigData(configData, {\n ...ctx,\n filePath: plugin.filePath || ctx.filePath,\n name: `${ctx.name} » plugin:${plugin.id}/${configName}`\n });\n }\n\n throw plugin.error || configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedShareableConfig(extendName, ctx) {\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n let request;\n\n if (isFilePath(extendName)) {\n request = extendName;\n } else if (extendName.startsWith(\".\")) {\n request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.\n } else {\n request = naming.normalizePackageName(\n extendName,\n \"eslint-config\"\n );\n }\n\n let filePath;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (error) {\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n throw configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n throw error;\n }\n\n writeDebugLogForLoading(request, relativeTo, filePath);\n return this._loadConfigData({\n ...ctx,\n filePath,\n name: `${ctx.name} » ${request}`\n });\n }\n\n /**\n * Load given plugins.\n * @param {string[]} names The plugin names to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {Record} The loaded parser.\n * @private\n */\n _loadPlugins(names, ctx) {\n return names.reduce((map, name) => {\n if (isFilePath(name)) {\n throw new Error(\"Plugins array cannot includes file paths.\");\n }\n const plugin = this._loadPlugin(name, ctx);\n\n map[plugin.id] = plugin;\n\n return map;\n }, {});\n }\n\n /**\n * Load a given parser.\n * @param {string} nameOrPath The package name or the path to a parser file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentParser} The loaded parser.\n */\n _loadParser(nameOrPath, ctx) {\n debug(\"Loading parser %j from %s\", nameOrPath, ctx.filePath);\n\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n\n try {\n const filePath = resolver.resolve(nameOrPath, relativeTo);\n\n writeDebugLogForLoading(nameOrPath, relativeTo, filePath);\n\n return new ConfigDependency({\n definition: require(filePath),\n filePath,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (error) {\n\n // If the parser name is \"espree\", load the espree of ESLint.\n if (nameOrPath === \"espree\") {\n debug(\"Fallback espree.\");\n return new ConfigDependency({\n definition: require(\"espree\"),\n filePath: require.resolve(\"espree\"),\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n debug(\"Failed to load parser '%s' declared in '%s'.\", nameOrPath, ctx.name);\n error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;\n\n return new ConfigDependency({\n error,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n }\n\n /**\n * Load a given plugin.\n * @param {string} name The plugin name to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentPlugin} The loaded plugin.\n * @private\n */\n _loadPlugin(name, ctx) {\n debug(\"Loading plugin %j from %s\", name, ctx.filePath);\n\n const { additionalPluginPool, resolver } = internalSlotsMap.get(this);\n const request = naming.normalizePackageName(name, \"eslint-plugin\");\n const id = naming.getShorthandName(request, \"eslint-plugin\");\n const relativeTo = path.join(ctx.pluginBasePath, \"__placeholder__.js\");\n\n if (name.match(/\\s+/u)) {\n const error = Object.assign(\n new Error(`Whitespace found in plugin name '${name}'`),\n {\n messageTemplate: \"whitespace-found\",\n messageData: { pluginName: request }\n }\n );\n\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n // Check for additional pool.\n const plugin =\n additionalPluginPool.get(request) ||\n additionalPluginPool.get(id);\n\n if (plugin) {\n return new ConfigDependency({\n definition: normalizePlugin(plugin),\n filePath: \"\", // It's unknown where the plugin came from.\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n let filePath;\n let error;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (resolveError) {\n error = resolveError;\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n error.messageTemplate = \"plugin-missing\";\n error.messageData = {\n pluginName: request,\n resolvePluginsRelativeTo: ctx.pluginBasePath,\n importerName: ctx.name\n };\n }\n }\n\n if (filePath) {\n try {\n writeDebugLogForLoading(request, relativeTo, filePath);\n\n const startTime = Date.now();\n const pluginDefinition = require(filePath);\n\n debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);\n\n return new ConfigDependency({\n definition: normalizePlugin(pluginDefinition),\n filePath,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (loadError) {\n error = loadError;\n }\n }\n\n debug(\"Failed to load plugin '%s' declared in '%s'.\", name, ctx.name);\n error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n /**\n * Take file expression processors as config array elements.\n * @param {Record} plugins The plugin definitions.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The config array elements of file expression processors.\n * @private\n */\n *_takeFileExtensionProcessors(plugins, ctx) {\n for (const pluginId of Object.keys(plugins)) {\n const processors =\n plugins[pluginId] &&\n plugins[pluginId].definition &&\n plugins[pluginId].definition.processors;\n\n if (!processors) {\n continue;\n }\n\n for (const processorId of Object.keys(processors)) {\n if (processorId.startsWith(\".\")) {\n yield* this._normalizeObjectConfigData(\n {\n files: [`*${processorId}`],\n processor: `${pluginId}/${processorId}`\n },\n {\n ...ctx,\n type: \"implicit-processor\",\n name: `${ctx.name}#processors[\"${pluginId}/${processorId}\"]`\n }\n );\n }\n }\n }\n }\n}\n\nexport { ConfigArrayFactory, createContext };\n","/**\n * @fileoverview `CascadingConfigArrayFactory` class.\n *\n * `CascadingConfigArrayFactory` class has a responsibility:\n *\n * 1. Handles cascading of config files.\n *\n * It provides two methods:\n *\n * - `getConfigArrayForFile(filePath)`\n * Get the corresponded configuration of a given file. This method doesn't\n * throw even if the given file didn't exist.\n * - `clearCache()`\n * Clear the internal cache. You have to call this method when\n * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends\n * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport { emitDeprecationWarning } from \"./shared/deprecation-warnings.js\";\n\nconst debug = debugOrig(\"eslintrc:cascading-config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {ReturnType} ConfigArray */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {ConfigData} [baseConfig] The config by `baseConfig` option.\n * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.\n * @property {string} [cwd] The base directory to start lookup.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]} [rulePaths] The value of `--rulesdir` option.\n * @property {string} [specificConfigPath] The value of `--config` option.\n * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryInternalSlots\n * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.\n * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.\n * @property {ConfigArray} cliConfigArray The config array of CLI options.\n * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.\n * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.\n * @property {Map} configCache The cache from directory paths to config arrays.\n * @property {string} cwd The base directory to start lookup.\n * @property {WeakMap} finalizeCache The cache from config arrays to finalized config arrays.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.\n * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.\n * @property {boolean} useEslintrc if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Create the config array from `baseConfig` and `rulePaths`.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createBaseConfigArray({\n configArrayFactory,\n baseConfigData,\n rulePaths,\n cwd,\n loadRules\n}) {\n const baseConfigArray = configArrayFactory.create(\n baseConfigData,\n { name: \"BaseConfig\" }\n );\n\n /*\n * Create the config array element for the default ignore patterns.\n * This element has `ignorePattern` property that ignores the default\n * patterns in the current working directory.\n */\n baseConfigArray.unshift(configArrayFactory.create(\n { ignorePatterns: IgnorePattern.DefaultPatterns },\n { name: \"DefaultIgnorePattern\" }\n )[0]);\n\n /*\n * Load rules `--rulesdir` option as a pseudo plugin.\n * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate\n * the rule's options with only information in the config array.\n */\n if (rulePaths && rulePaths.length > 0) {\n baseConfigArray.push({\n type: \"config\",\n name: \"--rulesdir\",\n filePath: \"\",\n plugins: {\n \"\": new ConfigDependency({\n definition: {\n rules: rulePaths.reduce(\n (map, rulesPath) => Object.assign(\n map,\n loadRules(rulesPath, cwd)\n ),\n {}\n )\n },\n filePath: \"\",\n id: \"\",\n importerName: \"--rulesdir\",\n importerPath: \"\"\n })\n }\n });\n }\n\n return baseConfigArray;\n}\n\n/**\n * Create the config array from CLI options.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n}) {\n const cliConfigArray = configArrayFactory.create(\n cliConfigData,\n { name: \"CLIOptions\" }\n );\n\n cliConfigArray.unshift(\n ...(ignorePath\n ? configArrayFactory.loadESLintIgnore(ignorePath)\n : configArrayFactory.loadDefaultESLintIgnore())\n );\n\n if (specificConfigPath) {\n cliConfigArray.unshift(\n ...configArrayFactory.loadFile(\n specificConfigPath,\n { name: \"--config\", basePath: cwd }\n )\n );\n }\n\n return cliConfigArray;\n}\n\n/**\n * The error type when there are files matched by a glob, but all of them have been ignored.\n */\nclass ConfigurationNotFoundError extends Error {\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @param {string} directoryPath The directory path.\n */\n constructor(directoryPath) {\n super(`No ESLint configuration found in ${directoryPath}.`);\n this.messageTemplate = \"no-config-found\";\n this.messageData = { directoryPath };\n }\n}\n\n/**\n * This class provides the functionality that enumerates every file which is\n * matched by given glob patterns and that configuration.\n */\nclass CascadingConfigArrayFactory {\n\n /**\n * Initialize this enumerator.\n * @param {CascadingConfigArrayFactoryOptions} options The options.\n */\n constructor({\n additionalPluginPool = new Map(),\n baseConfig: baseConfigData = null,\n cliConfig: cliConfigData = null,\n cwd = process.cwd(),\n ignorePath,\n resolvePluginsRelativeTo,\n rulePaths = [],\n specificConfigPath = null,\n useEslintrc = true,\n builtInRules = new Map(),\n loadRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n } = {}) {\n const configArrayFactory = new ConfigArrayFactory({\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo,\n builtInRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n });\n\n internalSlotsMap.set(this, {\n baseConfigArray: createBaseConfigArray({\n baseConfigData,\n configArrayFactory,\n cwd,\n rulePaths,\n loadRules,\n resolver\n }),\n baseConfigData,\n cliConfigArray: createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n }),\n cliConfigData,\n configArrayFactory,\n configCache: new Map(),\n cwd,\n finalizeCache: new WeakMap(),\n ignorePath,\n rulePaths,\n specificConfigPath,\n useEslintrc,\n builtInRules,\n loadRules\n });\n }\n\n /**\n * The path to the current working directory.\n * This is used by tests.\n * @type {string}\n */\n get cwd() {\n const { cwd } = internalSlotsMap.get(this);\n\n return cwd;\n }\n\n /**\n * Get the config array of a given file.\n * If `filePath` was not given, it returns the config which contains only\n * `baseConfigData` and `cliConfigData`.\n * @param {string} [filePath] The file path to a file.\n * @param {Object} [options] The options.\n * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The config array of the file.\n */\n getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {\n const {\n baseConfigArray,\n cliConfigArray,\n cwd\n } = internalSlotsMap.get(this);\n\n if (!filePath) {\n return new ConfigArray(...baseConfigArray, ...cliConfigArray);\n }\n\n const directoryPath = path.dirname(path.resolve(cwd, filePath));\n\n debug(`Load config files for ${directoryPath}.`);\n\n return this._finalizeConfigArray(\n this._loadConfigInAncestors(directoryPath),\n directoryPath,\n ignoreNotFoundError\n );\n }\n\n /**\n * Set the config data to override all configs.\n * Require to call `clearCache()` method after this method is called.\n * @param {ConfigData} configData The config data to override all configs.\n * @returns {void}\n */\n setOverrideConfig(configData) {\n const slots = internalSlotsMap.get(this);\n\n slots.cliConfigData = configData;\n }\n\n /**\n * Clear config cache.\n * @returns {void}\n */\n clearCache() {\n const slots = internalSlotsMap.get(this);\n\n slots.baseConfigArray = createBaseConfigArray(slots);\n slots.cliConfigArray = createCLIConfigArray(slots);\n slots.configCache.clear();\n }\n\n /**\n * Load and normalize config files from the ancestor directories.\n * @param {string} directoryPath The path to a leaf directory.\n * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {\n const {\n baseConfigArray,\n configArrayFactory,\n configCache,\n cwd,\n useEslintrc\n } = internalSlotsMap.get(this);\n\n if (!useEslintrc) {\n return baseConfigArray;\n }\n\n let configArray = configCache.get(directoryPath);\n\n // Hit cache.\n if (configArray) {\n debug(`Cache hit: ${directoryPath}.`);\n return configArray;\n }\n debug(`No cache found: ${directoryPath}.`);\n\n const homePath = os.homedir();\n\n // Consider this is root.\n if (directoryPath === homePath && cwd !== homePath) {\n debug(\"Stop traversing because of considered root.\");\n if (configsExistInSubdirs) {\n const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);\n\n if (filePath) {\n emitDeprecationWarning(\n filePath,\n \"ESLINT_PERSONAL_CONFIG_SUPPRESS\"\n );\n }\n }\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n\n // Load the config on this directory.\n try {\n configArray = configArrayFactory.loadInDirectory(directoryPath);\n } catch (error) {\n /* istanbul ignore next */\n if (error.code === \"EACCES\") {\n debug(\"Stop traversing because of 'EACCES' error.\");\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n throw error;\n }\n\n if (configArray.length > 0 && configArray.isRoot()) {\n debug(\"Stop traversing because of 'root:true'.\");\n configArray.unshift(...baseConfigArray);\n return this._cacheConfig(directoryPath, configArray);\n }\n\n // Load from the ancestors and merge it.\n const parentPath = path.dirname(directoryPath);\n const parentConfigArray = parentPath && parentPath !== directoryPath\n ? this._loadConfigInAncestors(\n parentPath,\n configsExistInSubdirs || configArray.length > 0\n )\n : baseConfigArray;\n\n if (configArray.length > 0) {\n configArray.unshift(...parentConfigArray);\n } else {\n configArray = parentConfigArray;\n }\n\n // Cache and return.\n return this._cacheConfig(directoryPath, configArray);\n }\n\n /**\n * Freeze and cache a given config.\n * @param {string} directoryPath The path to a directory as a cache key.\n * @param {ConfigArray} configArray The config array as a cache value.\n * @returns {ConfigArray} The `configArray` (frozen).\n */\n _cacheConfig(directoryPath, configArray) {\n const { configCache } = internalSlotsMap.get(this);\n\n Object.freeze(configArray);\n configCache.set(directoryPath, configArray);\n\n return configArray;\n }\n\n /**\n * Finalize a given config array.\n * Concatenate `--config` and other CLI options.\n * @param {ConfigArray} configArray The parent config array.\n * @param {string} directoryPath The path to the leaf directory to find config files.\n * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {\n const {\n cliConfigArray,\n configArrayFactory,\n finalizeCache,\n useEslintrc,\n builtInRules\n } = internalSlotsMap.get(this);\n\n let finalConfigArray = finalizeCache.get(configArray);\n\n if (!finalConfigArray) {\n finalConfigArray = configArray;\n\n // Load the personal config if there are no regular config files.\n if (\n useEslintrc &&\n configArray.every(c => !c.filePath) &&\n cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.\n ) {\n const homePath = os.homedir();\n\n debug(\"Loading the config file of the home directory:\", homePath);\n\n const personalConfigArray = configArrayFactory.loadInDirectory(\n homePath,\n { name: \"PersonalConfig\" }\n );\n\n if (\n personalConfigArray.length > 0 &&\n !directoryPath.startsWith(homePath)\n ) {\n const lastElement =\n personalConfigArray[personalConfigArray.length - 1];\n\n emitDeprecationWarning(\n lastElement.filePath,\n \"ESLINT_PERSONAL_CONFIG_LOAD\"\n );\n }\n\n finalConfigArray = finalConfigArray.concat(personalConfigArray);\n }\n\n // Apply CLI options.\n if (cliConfigArray.length > 0) {\n finalConfigArray = finalConfigArray.concat(cliConfigArray);\n }\n\n // Validate rule settings and environments.\n const validator = new ConfigValidator({\n builtInRules\n });\n\n validator.validateConfigArray(finalConfigArray);\n\n // Cache it.\n Object.freeze(finalConfigArray);\n finalizeCache.set(configArray, finalConfigArray);\n\n debug(\n \"Configuration was determined: %o on %s\",\n finalConfigArray,\n directoryPath\n );\n }\n\n // At least one element (the default ignore patterns) exists.\n if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {\n throw new ConfigurationNotFoundError(directoryPath);\n }\n\n return finalConfigArray;\n }\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport { CascadingConfigArrayFactory };\n","/**\n * @fileoverview Compatibility class for flat config.\n * @author Nicholas C. Zakas\n */\n\n//-----------------------------------------------------------------------------\n// Requirements\n//-----------------------------------------------------------------------------\n\nimport createDebug from \"debug\";\nimport path from \"path\";\n\nimport environments from \"../conf/environments.js\";\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n\nconst debug = createDebug(\"eslintrc:flat-compat\");\nconst cafactory = Symbol(\"cafactory\");\n\n/**\n * Translates an ESLintRC-style config object into a flag-config-style config\n * object.\n * @param {Object} eslintrcConfig An ESLintRC-style config object.\n * @param {Object} options Options to help translate the config.\n * @param {string} options.resolveConfigRelativeTo To the directory to resolve\n * configs from.\n * @param {string} options.resolvePluginsRelativeTo The directory to resolve\n * plugins from.\n * @param {ReadOnlyMap} options.pluginEnvironments A map of plugin environment\n * names to objects.\n * @param {ReadOnlyMap} options.pluginProcessors A map of plugin processor\n * names to objects.\n * @returns {Object} A flag-config-style config object.\n */\nfunction translateESLintRC(eslintrcConfig, {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo,\n pluginEnvironments,\n pluginProcessors\n}) {\n\n const flatConfig = {};\n const configs = [];\n const languageOptions = {};\n const linterOptions = {};\n const keysToCopy = [\"settings\", \"rules\", \"processor\"];\n const languageOptionsKeysToCopy = [\"globals\", \"parser\", \"parserOptions\"];\n const linterOptionsKeysToCopy = [\"noInlineConfig\", \"reportUnusedDisableDirectives\"];\n\n // check for special settings for eslint:all and eslint:recommended:\n if (eslintrcConfig.settings) {\n if (eslintrcConfig.settings[\"eslint:all\"] === true) {\n return [\"eslint:all\"];\n }\n\n if (eslintrcConfig.settings[\"eslint:recommended\"] === true) {\n return [\"eslint:recommended\"];\n }\n }\n\n // copy over simple translations\n for (const key of keysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig[key] = eslintrcConfig[key];\n }\n }\n\n // copy over languageOptions\n for (const key of languageOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n\n // create the languageOptions key in the flat config\n flatConfig.languageOptions = languageOptions;\n\n if (key === \"parser\") {\n debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);\n\n if (eslintrcConfig[key].error) {\n throw eslintrcConfig[key].error;\n }\n\n languageOptions[key] = eslintrcConfig[key].definition;\n continue;\n }\n\n // clone any object values that are in the eslintrc config\n if (eslintrcConfig[key] && typeof eslintrcConfig[key] === \"object\") {\n languageOptions[key] = {\n ...eslintrcConfig[key]\n };\n } else {\n languageOptions[key] = eslintrcConfig[key];\n }\n }\n }\n\n // copy over linterOptions\n for (const key of linterOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig.linterOptions = linterOptions;\n linterOptions[key] = eslintrcConfig[key];\n }\n }\n\n // move ecmaVersion a level up\n if (languageOptions.parserOptions) {\n\n if (\"ecmaVersion\" in languageOptions.parserOptions) {\n languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;\n delete languageOptions.parserOptions.ecmaVersion;\n }\n\n if (\"sourceType\" in languageOptions.parserOptions) {\n languageOptions.sourceType = languageOptions.parserOptions.sourceType;\n delete languageOptions.parserOptions.sourceType;\n }\n\n // check to see if we even need parserOptions anymore and remove it if not\n if (Object.keys(languageOptions.parserOptions).length === 0) {\n delete languageOptions.parserOptions;\n }\n }\n\n // overrides\n if (eslintrcConfig.criteria) {\n flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];\n }\n\n // translate plugins\n if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === \"object\") {\n debug(`Translating plugins: ${eslintrcConfig.plugins}`);\n\n flatConfig.plugins = {};\n\n for (const pluginName of Object.keys(eslintrcConfig.plugins)) {\n\n debug(`Translating plugin: ${pluginName}`);\n debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);\n\n const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];\n\n if (error) {\n throw error;\n }\n\n flatConfig.plugins[pluginName] = plugin;\n\n // create a config for any processors\n if (plugin.processors) {\n for (const processorName of Object.keys(plugin.processors)) {\n if (processorName.startsWith(\".\")) {\n debug(`Assigning processor: ${pluginName}/${processorName}`);\n\n configs.unshift({\n files: [`**/*${processorName}`],\n processor: pluginProcessors.get(`${pluginName}/${processorName}`)\n });\n }\n\n }\n }\n }\n }\n\n // translate env - must come after plugins\n if (eslintrcConfig.env && typeof eslintrcConfig.env === \"object\") {\n for (const envName of Object.keys(eslintrcConfig.env)) {\n\n // only add environments that are true\n if (eslintrcConfig.env[envName]) {\n debug(`Translating environment: ${envName}`);\n\n if (environments.has(envName)) {\n\n // built-in environments should be defined first\n configs.unshift(...translateESLintRC(environments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n } else if (pluginEnvironments.has(envName)) {\n\n // if the environment comes from a plugin, it should come after the plugin config\n configs.push(...translateESLintRC(pluginEnvironments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n }\n }\n }\n }\n\n // only add if there are actually keys in the config\n if (Object.keys(flatConfig).length > 0) {\n configs.push(flatConfig);\n }\n\n return configs;\n}\n\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\n/**\n * A compatibility class for working with configs.\n */\nclass FlatCompat {\n\n constructor({\n baseDirectory = process.cwd(),\n resolvePluginsRelativeTo = baseDirectory\n } = {}) {\n this.baseDirectory = baseDirectory;\n this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;\n this[cafactory] = new ConfigArrayFactory({\n cwd: baseDirectory,\n resolvePluginsRelativeTo,\n getEslintAllConfig: () => ({ settings: { \"eslint:all\": true } }),\n getEslintRecommendedConfig: () => ({ settings: { \"eslint:recommended\": true } })\n });\n }\n\n /**\n * Translates an ESLintRC-style config into a flag-config-style config.\n * @param {Object} eslintrcConfig The ESLintRC-style config object.\n * @returns {Object} A flag-config-style config object.\n */\n config(eslintrcConfig) {\n const eslintrcArray = this[cafactory].create(eslintrcConfig, {\n basePath: this.baseDirectory\n });\n\n const flatArray = [];\n let hasIgnorePatterns = false;\n\n eslintrcArray.forEach(configData => {\n if (configData.type === \"config\") {\n hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;\n flatArray.push(...translateESLintRC(configData, {\n resolveConfigRelativeTo: path.join(this.baseDirectory, \"__placeholder.js\"),\n resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, \"__placeholder.js\"),\n pluginEnvironments: eslintrcArray.pluginEnvironments,\n pluginProcessors: eslintrcArray.pluginProcessors\n }));\n }\n });\n\n // combine ignorePatterns to emulate ESLintRC behavior better\n if (hasIgnorePatterns) {\n flatArray.unshift({\n ignores: [filePath => {\n\n // Compute the final config for this file.\n // This filters config array elements by `files`/`excludedFiles` then merges the elements.\n const finalConfig = eslintrcArray.extractConfig(filePath);\n\n // Test the `ignorePattern` properties of the final config.\n return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);\n }]\n });\n }\n\n return flatArray;\n }\n\n /**\n * Translates the `env` section of an ESLintRC-style config.\n * @param {Object} envConfig The `env` section of an ESLintRC config.\n * @returns {Object} A flag-config object representing the environments.\n */\n env(envConfig) {\n return this.config({\n env: envConfig\n });\n }\n\n /**\n * Translates the `extends` section of an ESLintRC-style config.\n * @param {...string} configsToExtend The names of the configs to load.\n * @returns {Object} A flag-config object representing the config.\n */\n extends(...configsToExtend) {\n return this.config({\n extends: configsToExtend\n });\n }\n\n /**\n * Translates the `plugins` section of an ESLintRC-style config.\n * @param {...string} plugins The names of the plugins to load.\n * @returns {Object} A flag-config object representing the plugins.\n */\n plugins(...plugins) {\n return this.config({\n plugins\n });\n }\n}\n\nexport { FlatCompat };\n","/**\n * @fileoverview Package exports for @eslint/eslintrc\n * @author Nicholas C. Zakas\n */\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport {\n ConfigArrayFactory,\n createContext as createConfigArrayFactoryContext\n} from \"./config-array-factory.js\";\n\nimport { CascadingConfigArrayFactory } from \"./cascading-config-array-factory.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array/index.js\";\nimport { ConfigDependency } from \"./config-array/config-dependency.js\";\nimport { ExtractedConfig } from \"./config-array/extracted-config.js\";\nimport { IgnorePattern } from \"./config-array/ignore-pattern.js\";\nimport { OverrideTester } from \"./config-array/override-tester.js\";\nimport * as ConfigOps from \"./shared/config-ops.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport { FlatCompat } from \"./flat-compat.js\";\nimport environments from \"../conf/environments.js\";\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nconst Legacy = {\n ConfigArray,\n createConfigArrayFactoryContext,\n CascadingConfigArrayFactory,\n ConfigArrayFactory,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs,\n environments,\n\n // shared\n ConfigOps,\n ConfigValidator,\n ModuleResolver,\n naming\n};\n\nexport {\n\n Legacy,\n\n FlatCompat\n\n};\n"],"names":["debug","debugOrig","path","ignore","assert","internalSlotsMap","util","minimatch","Ajv","globals","BuiltInEnvironments","ConfigOps.normalizeConfigGlobal","Module","require","createRequire","fs","stripComments","importFresh","ModuleResolver.resolve","naming.normalizePackageName","naming.getShorthandName","os","createDebug","createConfigArrayFactoryContext"],"mappings":"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"} -\ No newline at end of file -diff --git a/lib/config-array-factory.js b/lib/config-array-factory.js -index 9553d1fde28c752d627fca17e6f8630218a4116e..3ea3e550c69ba8198c158b4660529e694ae9ae87 100644 ---- a/lib/config-array-factory.js -+++ b/lib/config-array-factory.js -@@ -40,7 +40,6 @@ - - import debugOrig from "debug"; - import fs from "fs"; --import importFresh from "import-fresh"; - import { createRequire } from "module"; - import path from "path"; - import stripComments from "strip-json-comments"; -@@ -231,7 +230,7 @@ function loadLegacyConfigFile(filePath) { - function loadJSConfigFile(filePath) { - debug(`Loading JS config file: ${filePath}`); - try { -- return importFresh(filePath); -+ return require(filePath); - } catch (e) { - debug(`Error reading JavaScript file: ${filePath}`); - e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`; diff --git a/.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch b/.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch new file mode 100644 index 000000000..f78666e86 --- /dev/null +++ b/.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch @@ -0,0 +1,59 @@ +diff --git a/dist/eslintrc.cjs b/dist/eslintrc.cjs +index 753117b3244df70d4305a599b9d97c346ddfac44..a47016aac3aed284c57b471fa0fb068a258e7b72 100644 +--- a/dist/eslintrc.cjs ++++ b/dist/eslintrc.cjs +@@ -4,7 +4,6 @@ Object.defineProperty(exports, '__esModule', { value: true }); + + var debugOrig = require('debug'); + var fs = require('fs'); +-var importFresh = require('import-fresh'); + var Module = require('module'); + var path = require('path'); + var stripComments = require('strip-json-comments'); +@@ -20,7 +19,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau + + var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig); + var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); +-var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh); + var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module); + var path__default = /*#__PURE__*/_interopDefaultLegacy(path); + var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments); +@@ -2559,7 +2557,7 @@ function loadLegacyConfigFile(filePath) { + function loadJSConfigFile(filePath) { + debug$2(`Loading JS config file: ${filePath}`); + try { +- return importFresh__default["default"](filePath); ++ return require$1(filePath); + } catch (e) { + debug$2(`Error reading JavaScript file: ${filePath}`); + e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`; +diff --git a/dist/eslintrc.cjs.map b/dist/eslintrc.cjs.map +index 58d9dbbcdea817cbf660935c6d1272f3313d0835..9e6ba45f7a045b6fb7ffa2f2f6c966ecaf0a6a55 100644 +--- a/dist/eslintrc.cjs.map ++++ b/dist/eslintrc.cjs.map +@@ -1 +1 @@ +-{"version":3,"file":"eslintrc.cjs","sources":["../lib/config-array/ignore-pattern.js","../lib/config-array/extracted-config.js","../lib/config-array/config-array.js","../lib/config-array/config-dependency.js","../lib/config-array/override-tester.js","../lib/config-array/index.js","../lib/shared/config-ops.js","../lib/shared/deprecation-warnings.js","../lib/shared/ajv.js","../conf/config-schema.js","../conf/environments.js","../lib/shared/config-validator.js","../lib/shared/naming.js","../lib/shared/relative-module-resolver.js","../lib/config-array-factory.js","../lib/cascading-config-array-factory.js","../lib/flat-compat.js","../lib/index.js"],"sourcesContent":["/**\n * @fileoverview `IgnorePattern` class.\n *\n * `IgnorePattern` class has the set of glob patterns and the base path.\n *\n * It provides two static methods.\n *\n * - `IgnorePattern.createDefaultIgnore(cwd)`\n * Create the default predicate function.\n * - `IgnorePattern.createIgnore(ignorePatterns)`\n * Create the predicate function from multiple `IgnorePattern` objects.\n *\n * It provides two properties and a method.\n *\n * - `patterns`\n * The glob patterns that ignore to lint.\n * - `basePath`\n * The base path of the glob patterns. If absolute paths existed in the\n * glob patterns, those are handled as relative paths to the base path.\n * - `getPatternsRelativeTo(basePath)`\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n *\n * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes\n * `ignorePatterns` properties.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport ignore from \"ignore\";\nimport debugOrig from \"debug\";\n\nconst debug = debugOrig(\"eslintrc:ignore-pattern\");\n\n/** @typedef {ReturnType} Ignore */\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the path to the common ancestor directory of given paths.\n * @param {string[]} sourcePaths The paths to calculate the common ancestor.\n * @returns {string} The path to the common ancestor directory.\n */\nfunction getCommonAncestorPath(sourcePaths) {\n let result = sourcePaths[0];\n\n for (let i = 1; i < sourcePaths.length; ++i) {\n const a = result;\n const b = sourcePaths[i];\n\n // Set the shorter one (it's the common ancestor if one includes the other).\n result = a.length < b.length ? a : b;\n\n // Set the common ancestor.\n for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {\n if (a[j] !== b[j]) {\n result = a.slice(0, lastSepPos);\n break;\n }\n if (a[j] === path.sep) {\n lastSepPos = j;\n }\n }\n }\n\n let resolvedResult = result || path.sep;\n\n // if Windows common ancestor is root of drive must have trailing slash to be absolute.\n if (resolvedResult && resolvedResult.endsWith(\":\") && process.platform === \"win32\") {\n resolvedResult += path.sep;\n }\n return resolvedResult;\n}\n\n/**\n * Make relative path.\n * @param {string} from The source path to get relative path.\n * @param {string} to The destination path to get relative path.\n * @returns {string} The relative path.\n */\nfunction relative(from, to) {\n const relPath = path.relative(from, to);\n\n if (path.sep === \"/\") {\n return relPath;\n }\n return relPath.split(path.sep).join(\"/\");\n}\n\n/**\n * Get the trailing slash if existed.\n * @param {string} filePath The path to check.\n * @returns {string} The trailing slash if existed.\n */\nfunction dirSuffix(filePath) {\n const isDir = (\n filePath.endsWith(path.sep) ||\n (process.platform === \"win32\" && filePath.endsWith(\"/\"))\n );\n\n return isDir ? \"/\" : \"\";\n}\n\nconst DefaultPatterns = Object.freeze([\"/**/node_modules/*\"]);\nconst DotPatterns = Object.freeze([\".*\", \"!.eslintrc.*\", \"!../\"]);\n\n//------------------------------------------------------------------------------\n// Public\n//------------------------------------------------------------------------------\n\nclass IgnorePattern {\n\n /**\n * The default patterns.\n * @type {string[]}\n */\n static get DefaultPatterns() {\n return DefaultPatterns;\n }\n\n /**\n * Create the default predicate function.\n * @param {string} cwd The current working directory.\n * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createDefaultIgnore(cwd) {\n return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);\n }\n\n /**\n * Create the predicate function from multiple `IgnorePattern` objects.\n * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.\n * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createIgnore(ignorePatterns) {\n debug(\"Create with: %o\", ignorePatterns);\n\n const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));\n const patterns = [].concat(\n ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))\n );\n const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);\n const dotIg = ignore({ allowRelativePaths: true }).add(patterns);\n\n debug(\" processed: %o\", { basePath, patterns });\n\n return Object.assign(\n (filePath, dot = false) => {\n assert(path.isAbsolute(filePath), \"'filePath' should be an absolute path.\");\n const relPathRaw = relative(basePath, filePath);\n const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));\n const adoptedIg = dot ? dotIg : ig;\n const result = relPath !== \"\" && adoptedIg.ignores(relPath);\n\n debug(\"Check\", { filePath, dot, relativePath: relPath, result });\n return result;\n },\n { basePath, patterns }\n );\n }\n\n /**\n * Initialize a new `IgnorePattern` instance.\n * @param {string[]} patterns The glob patterns that ignore to lint.\n * @param {string} basePath The base path of `patterns`.\n */\n constructor(patterns, basePath) {\n assert(path.isAbsolute(basePath), \"'basePath' should be an absolute path.\");\n\n /**\n * The glob patterns that ignore to lint.\n * @type {string[]}\n */\n this.patterns = patterns;\n\n /**\n * The base path of `patterns`.\n * @type {string}\n */\n this.basePath = basePath;\n\n /**\n * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.\n *\n * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.\n * It's `false` as-is for `ignorePatterns` property in config files.\n * @type {boolean}\n */\n this.loose = false;\n }\n\n /**\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n * @param {string} newBasePath The base path.\n * @returns {string[]} Modifired patterns.\n */\n getPatternsRelativeTo(newBasePath) {\n assert(path.isAbsolute(newBasePath), \"'newBasePath' should be an absolute path.\");\n const { basePath, loose, patterns } = this;\n\n if (newBasePath === basePath) {\n return patterns;\n }\n const prefix = `/${relative(newBasePath, basePath)}`;\n\n return patterns.map(pattern => {\n const negative = pattern.startsWith(\"!\");\n const head = negative ? \"!\" : \"\";\n const body = negative ? pattern.slice(1) : pattern;\n\n if (body.startsWith(\"/\") || body.startsWith(\"../\")) {\n return `${head}${prefix}${body}`;\n }\n return loose ? pattern : `${head}${prefix}/**/${body}`;\n });\n }\n}\n\nexport { IgnorePattern };\n","/**\n * @fileoverview `ExtractedConfig` class.\n *\n * `ExtractedConfig` class expresses a final configuration for a specific file.\n *\n * It provides one method.\n *\n * - `toCompatibleObjectAsConfigFileContent()`\n * Convert this configuration to the compatible object as the content of\n * config files. It converts the loaded parser and plugins to strings.\n * `CLIEngine#getConfigForFile(filePath)` method uses this method.\n *\n * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.\n *\n * @author Toru Nagashima \n */\n\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n// For VSCode intellisense\n/** @typedef {import(\"../../shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").SeverityConf} SeverityConf */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n\n/**\n * Check if `xs` starts with `ys`.\n * @template T\n * @param {T[]} xs The array to check.\n * @param {T[]} ys The array that may be the first part of `xs`.\n * @returns {boolean} `true` if `xs` starts with `ys`.\n */\nfunction startsWith(xs, ys) {\n return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);\n}\n\n/**\n * The class for extracted config data.\n */\nclass ExtractedConfig {\n constructor() {\n\n /**\n * The config name what `noInlineConfig` setting came from.\n * @type {string}\n */\n this.configNameOfNoInlineConfig = \"\";\n\n /**\n * Environments.\n * @type {Record}\n */\n this.env = {};\n\n /**\n * Global variables.\n * @type {Record}\n */\n this.globals = {};\n\n /**\n * The glob patterns that ignore to lint.\n * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}\n */\n this.ignores = void 0;\n\n /**\n * The flag that disables directive comments.\n * @type {boolean|undefined}\n */\n this.noInlineConfig = void 0;\n\n /**\n * Parser definition.\n * @type {DependentParser|null}\n */\n this.parser = null;\n\n /**\n * Options for the parser.\n * @type {Object}\n */\n this.parserOptions = {};\n\n /**\n * Plugin definitions.\n * @type {Record}\n */\n this.plugins = {};\n\n /**\n * Processor ID.\n * @type {string|null}\n */\n this.processor = null;\n\n /**\n * The flag that reports unused `eslint-disable` directive comments.\n * @type {boolean|undefined}\n */\n this.reportUnusedDisableDirectives = void 0;\n\n /**\n * Rule settings.\n * @type {Record}\n */\n this.rules = {};\n\n /**\n * Shared settings.\n * @type {Object}\n */\n this.settings = {};\n }\n\n /**\n * Convert this config to the compatible object as a config file content.\n * @returns {ConfigData} The converted object.\n */\n toCompatibleObjectAsConfigFileContent() {\n const {\n /* eslint-disable no-unused-vars */\n configNameOfNoInlineConfig: _ignore1,\n processor: _ignore2,\n /* eslint-enable no-unused-vars */\n ignores,\n ...config\n } = this;\n\n config.parser = config.parser && config.parser.filePath;\n config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();\n config.ignorePatterns = ignores ? ignores.patterns : [];\n\n // Strip the default patterns from `ignorePatterns`.\n if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {\n config.ignorePatterns =\n config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);\n }\n\n return config;\n }\n}\n\nexport { ExtractedConfig };\n","/**\n * @fileoverview `ConfigArray` class.\n *\n * `ConfigArray` class expresses the full of a configuration. It has the entry\n * config file, base config files that were extended, loaded parsers, and loaded\n * plugins.\n *\n * `ConfigArray` class provides three properties and two methods.\n *\n * - `pluginEnvironments`\n * - `pluginProcessors`\n * - `pluginRules`\n * The `Map` objects that contain the members of all plugins that this\n * config array contains. Those map objects don't have mutation methods.\n * Those keys are the member ID such as `pluginId/memberName`.\n * - `isRoot()`\n * If `true` then this configuration has `root:true` property.\n * - `extractConfig(filePath)`\n * Extract the final configuration for a given file. This means merging\n * every config array element which that `criteria` property matched. The\n * `filePath` argument must be an absolute path.\n *\n * `ConfigArrayFactory` provides the loading logic of config files.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").RuleConf} RuleConf */\n/** @typedef {import(\"../../shared/types\").Rule} Rule */\n/** @typedef {import(\"../../shared/types\").Plugin} Plugin */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {import(\"./override-tester\")[\"OverrideTester\"]} OverrideTester */\n\n/**\n * @typedef {Object} ConfigArrayElement\n * @property {string} name The name of this config element.\n * @property {string} filePath The path to the source file of this config element.\n * @property {InstanceType|null} criteria The tester for the `files` and `excludedFiles` of this config element.\n * @property {Record|undefined} env The environment settings.\n * @property {Record|undefined} globals The global variable settings.\n * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.\n * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.\n * @property {DependentParser|undefined} parser The parser loader.\n * @property {Object|undefined} parserOptions The parser options.\n * @property {Record|undefined} plugins The plugin loaders.\n * @property {string|undefined} processor The processor name to refer plugin's processor.\n * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.\n * @property {boolean|undefined} root The flag to express root.\n * @property {Record|undefined} rules The rule settings\n * @property {Object|undefined} settings The shared settings.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The element type.\n */\n\n/**\n * @typedef {Object} ConfigArrayInternalSlots\n * @property {Map} cache The cache to extract configs.\n * @property {ReadonlyMap|null} envMap The map from environment ID to environment definition.\n * @property {ReadonlyMap|null} processorMap The map from processor ID to environment definition.\n * @property {ReadonlyMap|null} ruleMap The map from rule ID to rule definition.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new class extends WeakMap {\n get(key) {\n let value = super.get(key);\n\n if (!value) {\n value = {\n cache: new Map(),\n envMap: null,\n processorMap: null,\n ruleMap: null\n };\n super.set(key, value);\n }\n\n return value;\n }\n}();\n\n/**\n * Get the indices which are matched to a given file.\n * @param {ConfigArrayElement[]} elements The elements.\n * @param {string} filePath The path to a target file.\n * @returns {number[]} The indices.\n */\nfunction getMatchedIndices(elements, filePath) {\n const indices = [];\n\n for (let i = elements.length - 1; i >= 0; --i) {\n const element = elements[i];\n\n if (!element.criteria || (filePath && element.criteria.test(filePath))) {\n indices.push(i);\n }\n }\n\n return indices;\n}\n\n/**\n * Check if a value is a non-null object.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is a non-null object.\n */\nfunction isNonNullObject(x) {\n return typeof x === \"object\" && x !== null;\n}\n\n/**\n * Merge two objects.\n *\n * Assign every property values of `y` to `x` if `x` doesn't have the property.\n * If `x`'s property value is an object, it does recursive.\n * @param {Object} target The destination to merge\n * @param {Object|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeWithoutOverwrite(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n\n if (isNonNullObject(target[key])) {\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (target[key] === void 0) {\n if (isNonNullObject(source[key])) {\n target[key] = Array.isArray(source[key]) ? [] : {};\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (source[key] !== void 0) {\n target[key] = source[key];\n }\n }\n }\n}\n\n/**\n * The error for plugin conflicts.\n */\nclass PluginConflictError extends Error {\n\n /**\n * Initialize this error object.\n * @param {string} pluginId The plugin ID.\n * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.\n */\n constructor(pluginId, plugins) {\n super(`Plugin \"${pluginId}\" was conflicted between ${plugins.map(p => `\"${p.importerName}\"`).join(\" and \")}.`);\n this.messageTemplate = \"plugin-conflict\";\n this.messageData = { pluginId, plugins };\n }\n}\n\n/**\n * Merge plugins.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergePlugins(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetValue = target[key];\n const sourceValue = source[key];\n\n // Adopt the plugin which was found at first.\n if (targetValue === void 0) {\n if (sourceValue.error) {\n throw sourceValue.error;\n }\n target[key] = sourceValue;\n } else if (sourceValue.filePath !== targetValue.filePath) {\n throw new PluginConflictError(key, [\n {\n filePath: targetValue.filePath,\n importerName: targetValue.importerName\n },\n {\n filePath: sourceValue.filePath,\n importerName: sourceValue.importerName\n }\n ]);\n }\n }\n}\n\n/**\n * Merge rule configs.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeRuleConfigs(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetDef = target[key];\n const sourceDef = source[key];\n\n // Adopt the rule config which was found at first.\n if (targetDef === void 0) {\n if (Array.isArray(sourceDef)) {\n target[key] = [...sourceDef];\n } else {\n target[key] = [sourceDef];\n }\n\n /*\n * If the first found rule config is severity only and the current rule\n * config has options, merge the severity and the options.\n */\n } else if (\n targetDef.length === 1 &&\n Array.isArray(sourceDef) &&\n sourceDef.length >= 2\n ) {\n targetDef.push(...sourceDef.slice(1));\n }\n }\n}\n\n/**\n * Create the extracted config.\n * @param {ConfigArray} instance The config elements.\n * @param {number[]} indices The indices to use.\n * @returns {ExtractedConfig} The extracted config.\n */\nfunction createConfig(instance, indices) {\n const config = new ExtractedConfig();\n const ignorePatterns = [];\n\n // Merge elements.\n for (const index of indices) {\n const element = instance[index];\n\n // Adopt the parser which was found at first.\n if (!config.parser && element.parser) {\n if (element.parser.error) {\n throw element.parser.error;\n }\n config.parser = element.parser;\n }\n\n // Adopt the processor which was found at first.\n if (!config.processor && element.processor) {\n config.processor = element.processor;\n }\n\n // Adopt the noInlineConfig which was found at first.\n if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {\n config.noInlineConfig = element.noInlineConfig;\n config.configNameOfNoInlineConfig = element.name;\n }\n\n // Adopt the reportUnusedDisableDirectives which was found at first.\n if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {\n config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;\n }\n\n // Collect ignorePatterns\n if (element.ignorePattern) {\n ignorePatterns.push(element.ignorePattern);\n }\n\n // Merge others.\n mergeWithoutOverwrite(config.env, element.env);\n mergeWithoutOverwrite(config.globals, element.globals);\n mergeWithoutOverwrite(config.parserOptions, element.parserOptions);\n mergeWithoutOverwrite(config.settings, element.settings);\n mergePlugins(config.plugins, element.plugins);\n mergeRuleConfigs(config.rules, element.rules);\n }\n\n // Create the predicate function for ignore patterns.\n if (ignorePatterns.length > 0) {\n config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());\n }\n\n return config;\n}\n\n/**\n * Collect definitions.\n * @template T, U\n * @param {string} pluginId The plugin ID for prefix.\n * @param {Record} defs The definitions to collect.\n * @param {Map} map The map to output.\n * @param {function(T): U} [normalize] The normalize function for each value.\n * @returns {void}\n */\nfunction collect(pluginId, defs, map, normalize) {\n if (defs) {\n const prefix = pluginId && `${pluginId}/`;\n\n for (const [key, value] of Object.entries(defs)) {\n map.set(\n `${prefix}${key}`,\n normalize ? normalize(value) : value\n );\n }\n }\n}\n\n/**\n * Normalize a rule definition.\n * @param {Function|Rule} rule The rule definition to normalize.\n * @returns {Rule} The normalized rule definition.\n */\nfunction normalizePluginRule(rule) {\n return typeof rule === \"function\" ? { create: rule } : rule;\n}\n\n/**\n * Delete the mutation methods from a given map.\n * @param {Map} map The map object to delete.\n * @returns {void}\n */\nfunction deleteMutationMethods(map) {\n Object.defineProperties(map, {\n clear: { configurable: true, value: void 0 },\n delete: { configurable: true, value: void 0 },\n set: { configurable: true, value: void 0 }\n });\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArrayElement[]} elements The config elements.\n * @param {ConfigArrayInternalSlots} slots The internal slots.\n * @returns {void}\n */\nfunction initPluginMemberMaps(elements, slots) {\n const processed = new Set();\n\n slots.envMap = new Map();\n slots.processorMap = new Map();\n slots.ruleMap = new Map();\n\n for (const element of elements) {\n if (!element.plugins) {\n continue;\n }\n\n for (const [pluginId, value] of Object.entries(element.plugins)) {\n const plugin = value.definition;\n\n if (!plugin || processed.has(pluginId)) {\n continue;\n }\n processed.add(pluginId);\n\n collect(pluginId, plugin.environments, slots.envMap);\n collect(pluginId, plugin.processors, slots.processorMap);\n collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);\n }\n }\n\n deleteMutationMethods(slots.envMap);\n deleteMutationMethods(slots.processorMap);\n deleteMutationMethods(slots.ruleMap);\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArray} instance The config elements.\n * @returns {ConfigArrayInternalSlots} The extracted config.\n */\nfunction ensurePluginMemberMaps(instance) {\n const slots = internalSlotsMap.get(instance);\n\n if (!slots.ruleMap) {\n initPluginMemberMaps(instance, slots);\n }\n\n return slots;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The Config Array.\n *\n * `ConfigArray` instance contains all settings, parsers, and plugins.\n * You need to call `ConfigArray#extractConfig(filePath)` method in order to\n * extract, merge and get only the config data which is related to an arbitrary\n * file.\n * @extends {Array}\n */\nclass ConfigArray extends Array {\n\n /**\n * Get the plugin environments.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin environments.\n */\n get pluginEnvironments() {\n return ensurePluginMemberMaps(this).envMap;\n }\n\n /**\n * Get the plugin processors.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin processors.\n */\n get pluginProcessors() {\n return ensurePluginMemberMaps(this).processorMap;\n }\n\n /**\n * Get the plugin rules.\n * The returned map cannot be mutated.\n * @returns {ReadonlyMap} The plugin rules.\n */\n get pluginRules() {\n return ensurePluginMemberMaps(this).ruleMap;\n }\n\n /**\n * Check if this config has `root` flag.\n * @returns {boolean} `true` if this config array is root.\n */\n isRoot() {\n for (let i = this.length - 1; i >= 0; --i) {\n const root = this[i].root;\n\n if (typeof root === \"boolean\") {\n return root;\n }\n }\n return false;\n }\n\n /**\n * Extract the config data which is related to a given file.\n * @param {string} filePath The absolute path to the target file.\n * @returns {ExtractedConfig} The extracted config data.\n */\n extractConfig(filePath) {\n const { cache } = internalSlotsMap.get(this);\n const indices = getMatchedIndices(this, filePath);\n const cacheKey = indices.join(\",\");\n\n if (!cache.has(cacheKey)) {\n cache.set(cacheKey, createConfig(this, indices));\n }\n\n return cache.get(cacheKey);\n }\n\n /**\n * Check if a given path is an additional lint target.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the file is an additional lint target.\n */\n isAdditionalTargetPath(filePath) {\n for (const { criteria, type } of this) {\n if (\n type === \"config\" &&\n criteria &&\n !criteria.endsWithWildcard &&\n criteria.test(filePath)\n ) {\n return true;\n }\n }\n return false;\n }\n}\n\n/**\n * Get the used extracted configs.\n * CLIEngine will use this method to collect used deprecated rules.\n * @param {ConfigArray} instance The config array object to get.\n * @returns {ExtractedConfig[]} The used extracted configs.\n * @private\n */\nfunction getUsedExtractedConfigs(instance) {\n const { cache } = internalSlotsMap.get(instance);\n\n return Array.from(cache.values());\n}\n\n\nexport {\n ConfigArray,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview `ConfigDependency` class.\n *\n * `ConfigDependency` class expresses a loaded parser or plugin.\n *\n * If the parser or plugin was loaded successfully, it has `definition` property\n * and `filePath` property. Otherwise, it has `error` property.\n *\n * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it\n * omits `definition` property.\n *\n * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers\n * or plugins.\n *\n * @author Toru Nagashima \n */\n\nimport util from \"util\";\n\n/**\n * The class is to store parsers or plugins.\n * This class hides the loaded object from `JSON.stringify()` and `console.log`.\n * @template T\n */\nclass ConfigDependency {\n\n /**\n * Initialize this instance.\n * @param {Object} data The dependency data.\n * @param {T} [data.definition] The dependency if the loading succeeded.\n * @param {Error} [data.error] The error object if the loading failed.\n * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.\n * @param {string} data.id The ID of this dependency.\n * @param {string} data.importerName The name of the config file which loads this dependency.\n * @param {string} data.importerPath The path to the config file which loads this dependency.\n */\n constructor({\n definition = null,\n error = null,\n filePath = null,\n id,\n importerName,\n importerPath\n }) {\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {T|null}\n */\n this.definition = definition;\n\n /**\n * The error object if the loading failed.\n * @type {Error|null}\n */\n this.error = error;\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {string|null}\n */\n this.filePath = filePath;\n\n /**\n * The ID of this dependency.\n * @type {string}\n */\n this.id = id;\n\n /**\n * The name of the config file which loads this dependency.\n * @type {string}\n */\n this.importerName = importerName;\n\n /**\n * The path to the config file which loads this dependency.\n * @type {string}\n */\n this.importerPath = importerPath;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n const obj = this[util.inspect.custom]();\n\n // Display `error.message` (`Error#message` is unenumerable).\n if (obj.error instanceof Error) {\n obj.error = { ...obj.error, message: obj.error.message };\n }\n\n return obj;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n const {\n definition: _ignore, // eslint-disable-line no-unused-vars\n ...obj\n } = this;\n\n return obj;\n }\n}\n\n/** @typedef {ConfigDependency} DependentParser */\n/** @typedef {ConfigDependency} DependentPlugin */\n\nexport { ConfigDependency };\n","/**\n * @fileoverview `OverrideTester` class.\n *\n * `OverrideTester` class handles `files` property and `excludedFiles` property\n * of `overrides` config.\n *\n * It provides one method.\n *\n * - `test(filePath)`\n * Test if a file path matches the pair of `files` property and\n * `excludedFiles` property. The `filePath` argument must be an absolute\n * path.\n *\n * `ConfigArrayFactory` creates `OverrideTester` objects when it processes\n * `overrides` properties.\n *\n * @author Toru Nagashima \n */\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport util from \"util\";\nimport minimatch from \"minimatch\";\n\nconst { Minimatch } = minimatch;\n\nconst minimatchOpts = { dot: true, matchBase: true };\n\n/**\n * @typedef {Object} Pattern\n * @property {InstanceType[] | null} includes The positive matchers.\n * @property {InstanceType[] | null} excludes The negative matchers.\n */\n\n/**\n * Normalize a given pattern to an array.\n * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.\n * @returns {string[]|null} Normalized patterns.\n * @private\n */\nfunction normalizePatterns(patterns) {\n if (Array.isArray(patterns)) {\n return patterns.filter(Boolean);\n }\n if (typeof patterns === \"string\" && patterns) {\n return [patterns];\n }\n return [];\n}\n\n/**\n * Create the matchers of given patterns.\n * @param {string[]} patterns The patterns.\n * @returns {InstanceType[] | null} The matchers.\n */\nfunction toMatcher(patterns) {\n if (patterns.length === 0) {\n return null;\n }\n return patterns.map(pattern => {\n if (/^\\.[/\\\\]/u.test(pattern)) {\n return new Minimatch(\n pattern.slice(2),\n\n // `./*.js` should not match with `subdir/foo.js`\n { ...minimatchOpts, matchBase: false }\n );\n }\n return new Minimatch(pattern, minimatchOpts);\n });\n}\n\n/**\n * Convert a given matcher to string.\n * @param {Pattern} matchers The matchers.\n * @returns {string} The string expression of the matcher.\n */\nfunction patternToJson({ includes, excludes }) {\n return {\n includes: includes && includes.map(m => m.pattern),\n excludes: excludes && excludes.map(m => m.pattern)\n };\n}\n\n/**\n * The class to test given paths are matched by the patterns.\n */\nclass OverrideTester {\n\n /**\n * Create a tester with given criteria.\n * If there are no criteria, returns `null`.\n * @param {string|string[]} files The glob patterns for included files.\n * @param {string|string[]} excludedFiles The glob patterns for excluded files.\n * @param {string} basePath The path to the base directory to test paths.\n * @returns {OverrideTester|null} The created instance or `null`.\n */\n static create(files, excludedFiles, basePath) {\n const includePatterns = normalizePatterns(files);\n const excludePatterns = normalizePatterns(excludedFiles);\n let endsWithWildcard = false;\n\n if (includePatterns.length === 0) {\n return null;\n }\n\n // Rejects absolute paths or relative paths to parents.\n for (const pattern of includePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n if (pattern.endsWith(\"*\")) {\n endsWithWildcard = true;\n }\n }\n for (const pattern of excludePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n }\n\n const includes = toMatcher(includePatterns);\n const excludes = toMatcher(excludePatterns);\n\n return new OverrideTester(\n [{ includes, excludes }],\n basePath,\n endsWithWildcard\n );\n }\n\n /**\n * Combine two testers by logical and.\n * If either of the testers was `null`, returns the other tester.\n * The `basePath` property of the two must be the same value.\n * @param {OverrideTester|null} a A tester.\n * @param {OverrideTester|null} b Another tester.\n * @returns {OverrideTester|null} Combined tester.\n */\n static and(a, b) {\n if (!b) {\n return a && new OverrideTester(\n a.patterns,\n a.basePath,\n a.endsWithWildcard\n );\n }\n if (!a) {\n return new OverrideTester(\n b.patterns,\n b.basePath,\n b.endsWithWildcard\n );\n }\n\n assert.strictEqual(a.basePath, b.basePath);\n return new OverrideTester(\n a.patterns.concat(b.patterns),\n a.basePath,\n a.endsWithWildcard || b.endsWithWildcard\n );\n }\n\n /**\n * Initialize this instance.\n * @param {Pattern[]} patterns The matchers.\n * @param {string} basePath The base path.\n * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.\n */\n constructor(patterns, basePath, endsWithWildcard = false) {\n\n /** @type {Pattern[]} */\n this.patterns = patterns;\n\n /** @type {string} */\n this.basePath = basePath;\n\n /** @type {boolean} */\n this.endsWithWildcard = endsWithWildcard;\n }\n\n /**\n * Test if a given path is matched or not.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the path was matched.\n */\n test(filePath) {\n if (typeof filePath !== \"string\" || !path.isAbsolute(filePath)) {\n throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);\n }\n const relativePath = path.relative(this.basePath, filePath);\n\n return this.patterns.every(({ includes, excludes }) => (\n (!includes || includes.some(m => m.match(relativePath))) &&\n (!excludes || !excludes.some(m => m.match(relativePath)))\n ));\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n if (this.patterns.length === 1) {\n return {\n ...patternToJson(this.patterns[0]),\n basePath: this.basePath\n };\n }\n return {\n AND: this.patterns.map(patternToJson),\n basePath: this.basePath\n };\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n return this.toJSON();\n }\n}\n\nexport { OverrideTester };\n","/**\n * @fileoverview `ConfigArray` class.\n * @author Toru Nagashima \n */\n\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array.js\";\nimport { ConfigDependency } from \"./config-dependency.js\";\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\nimport { OverrideTester } from \"./override-tester.js\";\n\nexport {\n ConfigArray,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview Config file operations. This file must be usable in the browser,\n * so no Node-specific code can be here.\n * @author Nicholas C. Zakas\n */\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\nconst RULE_SEVERITY_STRINGS = [\"off\", \"warn\", \"error\"],\n RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {\n map[value] = index;\n return map;\n }, {}),\n VALID_SEVERITIES = [0, 1, 2, \"off\", \"warn\", \"error\"];\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Normalizes the severity value of a rule's configuration to a number\n * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally\n * received from the user. A valid config value is either 0, 1, 2, the string \"off\" (treated the same as 0),\n * the string \"warn\" (treated the same as 1), the string \"error\" (treated the same as 2), or an array\n * whose first element is one of the above values. Strings are matched case-insensitively.\n * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.\n */\nfunction getRuleSeverity(ruleConfig) {\n const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (severityValue === 0 || severityValue === 1 || severityValue === 2) {\n return severityValue;\n }\n\n if (typeof severityValue === \"string\") {\n return RULE_SEVERITY[severityValue.toLowerCase()] || 0;\n }\n\n return 0;\n}\n\n/**\n * Converts old-style severity settings (0, 1, 2) into new-style\n * severity settings (off, warn, error) for all rules. Assumption is that severity\n * values have already been validated as correct.\n * @param {Object} config The config object to normalize.\n * @returns {void}\n */\nfunction normalizeToStrings(config) {\n\n if (config.rules) {\n Object.keys(config.rules).forEach(ruleId => {\n const ruleConfig = config.rules[ruleId];\n\n if (typeof ruleConfig === \"number\") {\n config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];\n } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === \"number\") {\n ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];\n }\n });\n }\n}\n\n/**\n * Determines if the severity for the given rule configuration represents an error.\n * @param {int|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} True if the rule represents an error, false if not.\n */\nfunction isErrorSeverity(ruleConfig) {\n return getRuleSeverity(ruleConfig) === 2;\n}\n\n/**\n * Checks whether a given config has valid severity or not.\n * @param {number|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isValidSeverity(ruleConfig) {\n let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (typeof severity === \"string\") {\n severity = severity.toLowerCase();\n }\n return VALID_SEVERITIES.indexOf(severity) !== -1;\n}\n\n/**\n * Checks whether every rule of a given config has valid severity or not.\n * @param {Object} config The configuration for rules.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isEverySeverityValid(config) {\n return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));\n}\n\n/**\n * Normalizes a value for a global in a config\n * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in\n * a global directive comment\n * @returns {(\"readable\"|\"writeable\"|\"off\")} The value normalized as a string\n * @throws Error if global value is invalid\n */\nfunction normalizeConfigGlobal(configuredValue) {\n switch (configuredValue) {\n case \"off\":\n return \"off\";\n\n case true:\n case \"true\":\n case \"writeable\":\n case \"writable\":\n return \"writable\";\n\n case null:\n case false:\n case \"false\":\n case \"readable\":\n case \"readonly\":\n return \"readonly\";\n\n default:\n throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);\n }\n}\n\nexport {\n getRuleSeverity,\n normalizeToStrings,\n isErrorSeverity,\n isValidSeverity,\n isEverySeverityValid,\n normalizeConfigGlobal\n};\n","/**\n * @fileoverview Provide the function that emits deprecation warnings.\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport path from \"path\";\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\n// Defitions for deprecation warnings.\nconst deprecationWarningMessages = {\n ESLINT_LEGACY_ECMAFEATURES:\n \"The 'ecmaFeatures' config file property is deprecated and has no effect.\",\n ESLINT_PERSONAL_CONFIG_LOAD:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please use a config file per project or the '--config' option.\",\n ESLINT_PERSONAL_CONFIG_SUPPRESS:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please remove it or add 'root:true' to the config files in your \" +\n \"projects in order to avoid loading '~/.eslintrc.*' accidentally.\"\n};\n\nconst sourceFileErrorCache = new Set();\n\n/**\n * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted\n * for each unique file path, but repeated invocations with the same file path have no effect.\n * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.\n * @param {string} source The name of the configuration source to report the warning for.\n * @param {string} errorCode The warning message to show.\n * @returns {void}\n */\nfunction emitDeprecationWarning(source, errorCode) {\n const cacheKey = JSON.stringify({ source, errorCode });\n\n if (sourceFileErrorCache.has(cacheKey)) {\n return;\n }\n sourceFileErrorCache.add(cacheKey);\n\n const rel = path.relative(process.cwd(), source);\n const message = deprecationWarningMessages[errorCode];\n\n process.emitWarning(\n `${message} (found in \"${rel}\")`,\n \"DeprecationWarning\",\n errorCode\n );\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n emitDeprecationWarning\n};\n","/**\n * @fileoverview The instance of Ajv validator.\n * @author Evgeny Poberezkin\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport Ajv from \"ajv\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/*\n * Copied from ajv/lib/refs/json-schema-draft-04.json\n * The MIT License (MIT)\n * Copyright (c) 2015-2017 Evgeny Poberezkin\n */\nconst metaSchema = {\n id: \"http://json-schema.org/draft-04/schema#\",\n $schema: \"http://json-schema.org/draft-04/schema#\",\n description: \"Core schema meta-schema\",\n definitions: {\n schemaArray: {\n type: \"array\",\n minItems: 1,\n items: { $ref: \"#\" }\n },\n positiveInteger: {\n type: \"integer\",\n minimum: 0\n },\n positiveIntegerDefault0: {\n allOf: [{ $ref: \"#/definitions/positiveInteger\" }, { default: 0 }]\n },\n simpleTypes: {\n enum: [\"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\"]\n },\n stringArray: {\n type: \"array\",\n items: { type: \"string\" },\n minItems: 1,\n uniqueItems: true\n }\n },\n type: \"object\",\n properties: {\n id: {\n type: \"string\"\n },\n $schema: {\n type: \"string\"\n },\n title: {\n type: \"string\"\n },\n description: {\n type: \"string\"\n },\n default: { },\n multipleOf: {\n type: \"number\",\n minimum: 0,\n exclusiveMinimum: true\n },\n maximum: {\n type: \"number\"\n },\n exclusiveMaximum: {\n type: \"boolean\",\n default: false\n },\n minimum: {\n type: \"number\"\n },\n exclusiveMinimum: {\n type: \"boolean\",\n default: false\n },\n maxLength: { $ref: \"#/definitions/positiveInteger\" },\n minLength: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n pattern: {\n type: \"string\",\n format: \"regex\"\n },\n additionalItems: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n items: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/schemaArray\" }\n ],\n default: { }\n },\n maxItems: { $ref: \"#/definitions/positiveInteger\" },\n minItems: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n uniqueItems: {\n type: \"boolean\",\n default: false\n },\n maxProperties: { $ref: \"#/definitions/positiveInteger\" },\n minProperties: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n required: { $ref: \"#/definitions/stringArray\" },\n additionalProperties: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n definitions: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n properties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n patternProperties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n dependencies: {\n type: \"object\",\n additionalProperties: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/stringArray\" }\n ]\n }\n },\n enum: {\n type: \"array\",\n minItems: 1,\n uniqueItems: true\n },\n type: {\n anyOf: [\n { $ref: \"#/definitions/simpleTypes\" },\n {\n type: \"array\",\n items: { $ref: \"#/definitions/simpleTypes\" },\n minItems: 1,\n uniqueItems: true\n }\n ]\n },\n format: { type: \"string\" },\n allOf: { $ref: \"#/definitions/schemaArray\" },\n anyOf: { $ref: \"#/definitions/schemaArray\" },\n oneOf: { $ref: \"#/definitions/schemaArray\" },\n not: { $ref: \"#\" }\n },\n dependencies: {\n exclusiveMaximum: [\"maximum\"],\n exclusiveMinimum: [\"minimum\"]\n },\n default: { }\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport default (additionalOptions = {}) => {\n const ajv = new Ajv({\n meta: false,\n useDefaults: true,\n validateSchema: false,\n missingRefs: \"ignore\",\n verbose: true,\n schemaId: \"auto\",\n ...additionalOptions\n });\n\n ajv.addMetaSchema(metaSchema);\n // eslint-disable-next-line no-underscore-dangle\n ajv._opts.defaultMeta = metaSchema.id;\n\n return ajv;\n};\n","/**\n * @fileoverview Defines a schema for configs.\n * @author Sylvan Mably\n */\n\nconst baseConfigProperties = {\n $schema: { type: \"string\" },\n env: { type: \"object\" },\n extends: { $ref: \"#/definitions/stringOrStrings\" },\n globals: { type: \"object\" },\n overrides: {\n type: \"array\",\n items: { $ref: \"#/definitions/overrideConfig\" },\n additionalItems: false\n },\n parser: { type: [\"string\", \"null\"] },\n parserOptions: { type: \"object\" },\n plugins: { type: \"array\" },\n processor: { type: \"string\" },\n rules: { type: \"object\" },\n settings: { type: \"object\" },\n noInlineConfig: { type: \"boolean\" },\n reportUnusedDisableDirectives: { type: \"boolean\" },\n\n ecmaFeatures: { type: \"object\" } // deprecated; logs a warning when used\n};\n\nconst configSchema = {\n definitions: {\n stringOrStrings: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false\n }\n ]\n },\n stringOrStringsRequired: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false,\n minItems: 1\n }\n ]\n },\n\n // Config at top-level.\n objectConfig: {\n type: \"object\",\n properties: {\n root: { type: \"boolean\" },\n ignorePatterns: { $ref: \"#/definitions/stringOrStrings\" },\n ...baseConfigProperties\n },\n additionalProperties: false\n },\n\n // Config in `overrides`.\n overrideConfig: {\n type: \"object\",\n properties: {\n excludedFiles: { $ref: \"#/definitions/stringOrStrings\" },\n files: { $ref: \"#/definitions/stringOrStringsRequired\" },\n ...baseConfigProperties\n },\n required: [\"files\"],\n additionalProperties: false\n }\n },\n\n $ref: \"#/definitions/objectConfig\"\n};\n\nexport default configSchema;\n","/**\n * @fileoverview Defines environment settings and globals.\n * @author Elan Shanker\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport globals from \"globals\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the object that has difference.\n * @param {Record} current The newer object.\n * @param {Record} prev The older object.\n * @returns {Record} The difference object.\n */\nfunction getDiff(current, prev) {\n const retv = {};\n\n for (const [key, value] of Object.entries(current)) {\n if (!Object.hasOwnProperty.call(prev, key)) {\n retv[key] = value;\n }\n }\n\n return retv;\n}\n\nconst newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...\nconst newGlobals2017 = {\n Atomics: false,\n SharedArrayBuffer: false\n};\nconst newGlobals2020 = {\n BigInt: false,\n BigInt64Array: false,\n BigUint64Array: false,\n globalThis: false\n};\n\nconst newGlobals2021 = {\n AggregateError: false,\n FinalizationRegistry: false,\n WeakRef: false\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/** @type {Map} */\nexport default new Map(Object.entries({\n\n // Language\n builtin: {\n globals: globals.es5\n },\n es6: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2015: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2016: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 7\n }\n },\n es2017: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 8\n }\n },\n es2018: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 9\n }\n },\n es2019: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 10\n }\n },\n es2020: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },\n parserOptions: {\n ecmaVersion: 11\n }\n },\n es2021: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 12\n }\n },\n es2022: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 13\n }\n },\n\n // Platforms\n browser: {\n globals: globals.browser\n },\n node: {\n globals: globals.node,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n \"shared-node-browser\": {\n globals: globals[\"shared-node-browser\"]\n },\n worker: {\n globals: globals.worker\n },\n serviceworker: {\n globals: globals.serviceworker\n },\n\n // Frameworks\n commonjs: {\n globals: globals.commonjs,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n amd: {\n globals: globals.amd\n },\n mocha: {\n globals: globals.mocha\n },\n jasmine: {\n globals: globals.jasmine\n },\n jest: {\n globals: globals.jest\n },\n phantomjs: {\n globals: globals.phantomjs\n },\n jquery: {\n globals: globals.jquery\n },\n qunit: {\n globals: globals.qunit\n },\n prototypejs: {\n globals: globals.prototypejs\n },\n shelljs: {\n globals: globals.shelljs\n },\n meteor: {\n globals: globals.meteor\n },\n mongo: {\n globals: globals.mongo\n },\n protractor: {\n globals: globals.protractor\n },\n applescript: {\n globals: globals.applescript\n },\n nashorn: {\n globals: globals.nashorn\n },\n atomtest: {\n globals: globals.atomtest\n },\n embertest: {\n globals: globals.embertest\n },\n webextensions: {\n globals: globals.webextensions\n },\n greasemonkey: {\n globals: globals.greasemonkey\n }\n}));\n","/**\n * @fileoverview Validates configs.\n * @author Brandon Mills\n */\n\n/* eslint class-methods-use-this: \"off\" */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport util from \"util\";\nimport * as ConfigOps from \"./config-ops.js\";\nimport { emitDeprecationWarning } from \"./deprecation-warnings.js\";\nimport ajvOrig from \"./ajv.js\";\nimport configSchema from \"../../conf/config-schema.js\";\nimport BuiltInEnvironments from \"../../conf/environments.js\";\n\nconst ajv = ajvOrig();\n\nconst ruleValidators = new WeakMap();\nconst noop = Function.prototype;\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\nlet validateSchema;\nconst severityMap = {\n error: 2,\n warn: 1,\n off: 0\n};\n\nconst validated = new WeakSet();\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nexport default class ConfigValidator {\n constructor({ builtInRules = new Map() } = {}) {\n this.builtInRules = builtInRules;\n }\n\n /**\n * Gets a complete options schema for a rule.\n * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object\n * @returns {Object} JSON Schema for the rule's options.\n */\n getRuleOptionsSchema(rule) {\n if (!rule) {\n return null;\n }\n\n const schema = rule.schema || rule.meta && rule.meta.schema;\n\n // Given a tuple of schemas, insert warning level at the beginning\n if (Array.isArray(schema)) {\n if (schema.length) {\n return {\n type: \"array\",\n items: schema,\n minItems: 0,\n maxItems: schema.length\n };\n }\n return {\n type: \"array\",\n minItems: 0,\n maxItems: 0\n };\n\n }\n\n // Given a full schema, leave it alone\n return schema || null;\n }\n\n /**\n * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.\n * @param {options} options The given options for the rule.\n * @returns {number|string} The rule's severity value\n */\n validateRuleSeverity(options) {\n const severity = Array.isArray(options) ? options[0] : options;\n const normSeverity = typeof severity === \"string\" ? severityMap[severity.toLowerCase()] : severity;\n\n if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {\n return normSeverity;\n }\n\n throw new Error(`\\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, \"\\\"\").replace(/\\n/gu, \"\")}').\\n`);\n\n }\n\n /**\n * Validates the non-severity options passed to a rule, based on its schema.\n * @param {{create: Function}} rule The rule to validate\n * @param {Array} localOptions The options for the rule, excluding severity\n * @returns {void}\n */\n validateRuleSchema(rule, localOptions) {\n if (!ruleValidators.has(rule)) {\n const schema = this.getRuleOptionsSchema(rule);\n\n if (schema) {\n ruleValidators.set(rule, ajv.compile(schema));\n }\n }\n\n const validateRule = ruleValidators.get(rule);\n\n if (validateRule) {\n validateRule(localOptions);\n if (validateRule.errors) {\n throw new Error(validateRule.errors.map(\n error => `\\tValue ${JSON.stringify(error.data)} ${error.message}.\\n`\n ).join(\"\"));\n }\n }\n }\n\n /**\n * Validates a rule's options against its schema.\n * @param {{create: Function}|null} rule The rule that the config is being validated for\n * @param {string} ruleId The rule's unique name.\n * @param {Array|number} options The given options for the rule.\n * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,\n * no source is prepended to the message.\n * @returns {void}\n */\n validateRuleOptions(rule, ruleId, options, source = null) {\n try {\n const severity = this.validateRuleSeverity(options);\n\n if (severity !== 0) {\n this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);\n }\n } catch (err) {\n const enhancedMessage = `Configuration for rule \"${ruleId}\" is invalid:\\n${err.message}`;\n\n if (typeof source === \"string\") {\n throw new Error(`${source}:\\n\\t${enhancedMessage}`);\n } else {\n throw new Error(enhancedMessage);\n }\n }\n }\n\n /**\n * Validates an environment object\n * @param {Object} environment The environment config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.\n * @returns {void}\n */\n validateEnvironment(\n environment,\n source,\n getAdditionalEnv = noop\n ) {\n\n // not having an environment is ok\n if (!environment) {\n return;\n }\n\n Object.keys(environment).forEach(id => {\n const env = getAdditionalEnv(id) || BuiltInEnvironments.get(id) || null;\n\n if (!env) {\n const message = `${source}:\\n\\tEnvironment key \"${id}\" is unknown\\n`;\n\n throw new Error(message);\n }\n });\n }\n\n /**\n * Validates a rules config object\n * @param {Object} rulesConfig The rules config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules\n * @returns {void}\n */\n validateRules(\n rulesConfig,\n source,\n getAdditionalRule = noop\n ) {\n if (!rulesConfig) {\n return;\n }\n\n Object.keys(rulesConfig).forEach(id => {\n const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;\n\n this.validateRuleOptions(rule, id, rulesConfig[id], source);\n });\n }\n\n /**\n * Validates a `globals` section of a config file\n * @param {Object} globalsConfig The `globals` section\n * @param {string|null} source The name of the configuration source to report in the event of an error.\n * @returns {void}\n */\n validateGlobals(globalsConfig, source = null) {\n if (!globalsConfig) {\n return;\n }\n\n Object.entries(globalsConfig)\n .forEach(([configuredGlobal, configuredValue]) => {\n try {\n ConfigOps.normalizeConfigGlobal(configuredValue);\n } catch (err) {\n throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\\n${err.message}`);\n }\n });\n }\n\n /**\n * Validate `processor` configuration.\n * @param {string|undefined} processorName The processor name.\n * @param {string} source The name of config file.\n * @param {function(id:string): Processor} getProcessor The getter of defined processors.\n * @returns {void}\n */\n validateProcessor(processorName, source, getProcessor) {\n if (processorName && !getProcessor(processorName)) {\n throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);\n }\n }\n\n /**\n * Formats an array of schema validation errors.\n * @param {Array} errors An array of error messages to format.\n * @returns {string} Formatted error message\n */\n formatErrors(errors) {\n return errors.map(error => {\n if (error.keyword === \"additionalProperties\") {\n const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;\n\n return `Unexpected top-level property \"${formattedPropertyPath}\"`;\n }\n if (error.keyword === \"type\") {\n const formattedField = error.dataPath.slice(1);\n const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join(\"/\") : error.schema;\n const formattedValue = JSON.stringify(error.data);\n\n return `Property \"${formattedField}\" is the wrong type (expected ${formattedExpectedType} but got \\`${formattedValue}\\`)`;\n }\n\n const field = error.dataPath[0] === \".\" ? error.dataPath.slice(1) : error.dataPath;\n\n return `\"${field}\" ${error.message}. Value: ${JSON.stringify(error.data)}`;\n }).map(message => `\\t- ${message}.\\n`).join(\"\");\n }\n\n /**\n * Validates the top level properties of the config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @returns {void}\n */\n validateConfigSchema(config, source = null) {\n validateSchema = validateSchema || ajv.compile(configSchema);\n\n if (!validateSchema(config)) {\n throw new Error(`ESLint configuration in ${source} is invalid:\\n${this.formatErrors(validateSchema.errors)}`);\n }\n\n if (Object.hasOwnProperty.call(config, \"ecmaFeatures\")) {\n emitDeprecationWarning(source, \"ESLINT_LEGACY_ECMAFEATURES\");\n }\n }\n\n /**\n * Validates an entire config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.\n * @returns {void}\n */\n validate(config, source, getAdditionalRule, getAdditionalEnv) {\n this.validateConfigSchema(config, source);\n this.validateRules(config.rules, source, getAdditionalRule);\n this.validateEnvironment(config.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n\n for (const override of config.overrides || []) {\n this.validateRules(override.rules, source, getAdditionalRule);\n this.validateEnvironment(override.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n }\n }\n\n /**\n * Validate config array object.\n * @param {ConfigArray} configArray The config array to validate.\n * @returns {void}\n */\n validateConfigArray(configArray) {\n const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);\n const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);\n const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);\n\n // Validate.\n for (const element of configArray) {\n if (validated.has(element)) {\n continue;\n }\n validated.add(element);\n\n this.validateEnvironment(element.env, element.name, getPluginEnv);\n this.validateGlobals(element.globals, element.name);\n this.validateProcessor(element.processor, element.name, getPluginProcessor);\n this.validateRules(element.rules, element.name, getPluginRule);\n }\n }\n\n}\n","/**\n * @fileoverview Common helpers for naming of plugins, formatters and configs\n */\n\nconst NAMESPACE_REGEX = /^@.*\\//iu;\n\n/**\n * Brings package name to correct format based on prefix\n * @param {string} name The name of the package.\n * @param {string} prefix Can be either \"eslint-plugin\", \"eslint-config\" or \"eslint-formatter\"\n * @returns {string} Normalized name of the package\n * @private\n */\nfunction normalizePackageName(name, prefix) {\n let normalizedName = name;\n\n /**\n * On Windows, name can come in with Windows slashes instead of Unix slashes.\n * Normalize to Unix first to avoid errors later on.\n * https://github.com/eslint/eslint/issues/5644\n */\n if (normalizedName.includes(\"\\\\\")) {\n normalizedName = normalizedName.replace(/\\\\/gu, \"/\");\n }\n\n if (normalizedName.charAt(0) === \"@\") {\n\n /**\n * it's a scoped package\n * package name is the prefix, or just a username\n */\n const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, \"u\"),\n scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, \"u\");\n\n if (scopedPackageShortcutRegex.test(normalizedName)) {\n normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);\n } else if (!scopedPackageNameRegex.test(normalizedName.split(\"/\")[1])) {\n\n /**\n * for scoped packages, insert the prefix after the first / unless\n * the path is already @scope/eslint or @scope/eslint-xxx-yyy\n */\n normalizedName = normalizedName.replace(/^@([^/]+)\\/(.*)$/u, `@$1/${prefix}-$2`);\n }\n } else if (!normalizedName.startsWith(`${prefix}-`)) {\n normalizedName = `${prefix}-${normalizedName}`;\n }\n\n return normalizedName;\n}\n\n/**\n * Removes the prefix from a fullname.\n * @param {string} fullname The term which may have the prefix.\n * @param {string} prefix The prefix to remove.\n * @returns {string} The term without prefix.\n */\nfunction getShorthandName(fullname, prefix) {\n if (fullname[0] === \"@\") {\n let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, \"u\").exec(fullname);\n\n if (matchResult) {\n return matchResult[1];\n }\n\n matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, \"u\").exec(fullname);\n if (matchResult) {\n return `${matchResult[1]}/${matchResult[2]}`;\n }\n } else if (fullname.startsWith(`${prefix}-`)) {\n return fullname.slice(prefix.length + 1);\n }\n\n return fullname;\n}\n\n/**\n * Gets the scope (namespace) of a term.\n * @param {string} term The term which may have the namespace.\n * @returns {string} The namespace of the term if it has one.\n */\nfunction getNamespaceFromTerm(term) {\n const match = term.match(NAMESPACE_REGEX);\n\n return match ? match[0] : \"\";\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n normalizePackageName,\n getShorthandName,\n getNamespaceFromTerm\n};\n","/**\n * Utility for resolving a module relative to another module\n * @author Teddy Katz\n */\n\nimport Module from \"module\";\n\n/*\n * `Module.createRequire` is added in v12.2.0. It supports URL as well.\n * We only support the case where the argument is a filepath, not a URL.\n */\nconst createRequire = Module.createRequire;\n\n/**\n * Resolves a Node module relative to another module\n * @param {string} moduleName The name of a Node module, or a path to a Node module.\n * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be\n * a file rather than a directory, but the file need not actually exist.\n * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`\n */\nfunction resolve(moduleName, relativeToPath) {\n try {\n return createRequire(relativeToPath).resolve(moduleName);\n } catch (error) {\n\n // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.\n if (\n typeof error === \"object\" &&\n error !== null &&\n error.code === \"MODULE_NOT_FOUND\" &&\n !error.requireStack &&\n error.message.includes(moduleName)\n ) {\n error.message += `\\nRequire stack:\\n- ${relativeToPath}`;\n }\n throw error;\n }\n}\n\nexport {\n resolve\n};\n","/**\n * @fileoverview The factory of `ConfigArray` objects.\n *\n * This class provides methods to create `ConfigArray` instance.\n *\n * - `create(configData, options)`\n * Create a `ConfigArray` instance from a config data. This is to handle CLI\n * options except `--config`.\n * - `loadFile(filePath, options)`\n * Create a `ConfigArray` instance from a config file. This is to handle\n * `--config` option. If the file was not found, throws the following error:\n * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.\n * - If the filename was `package.json`, an IO error or an\n * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.\n * - Otherwise, an IO error such as `ENOENT`.\n * - `loadInDirectory(directoryPath, options)`\n * Create a `ConfigArray` instance from a config file which is on a given\n * directory. This tries to load `.eslintrc.*` or `package.json`. If not\n * found, returns an empty `ConfigArray`.\n * - `loadESLintIgnore(filePath)`\n * Create a `ConfigArray` instance from a config file that is `.eslintignore`\n * format. This is to handle `--ignore-path` option.\n * - `loadDefaultESLintIgnore()`\n * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in\n * the current working directory.\n *\n * `ConfigArrayFactory` class has the responsibility that loads configuration\n * files, including loading `extends`, `parser`, and `plugins`. The created\n * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.\n *\n * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class\n * handles cascading and hierarchy.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport fs from \"fs\";\nimport importFresh from \"import-fresh\";\nimport { createRequire } from \"module\";\nimport path from \"path\";\nimport stripComments from \"strip-json-comments\";\n\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern,\n OverrideTester\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\n\nconst require = createRequire(import.meta.url);\n\nconst debug = debugOrig(\"eslintrc:config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\nconst configFilenames = [\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \".eslintrc.json\",\n \".eslintrc\",\n \"package.json\"\n];\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").OverrideConfigData} OverrideConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {import(\"./config-array/config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-array/config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {ConfigArray[0]} ConfigArrayElement */\n\n/**\n * @typedef {Object} ConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {string} [cwd] The path to the current working directory.\n * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryInternalSlots\n * @property {Map} additionalPluginPool The map for additional plugins.\n * @property {string} cwd The path to the current working directory.\n * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {string} pluginBasePath The base path to resolve plugins.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/** @type {WeakMap} */\nconst normalizedPlugins = new WeakMap();\n\n/**\n * Check if a given string is a file path.\n * @param {string} nameOrPath A module name or file path.\n * @returns {boolean} `true` if the `nameOrPath` is a file path.\n */\nfunction isFilePath(nameOrPath) {\n return (\n /^\\.{1,2}[/\\\\]/u.test(nameOrPath) ||\n path.isAbsolute(nameOrPath)\n );\n}\n\n/**\n * Convenience wrapper for synchronously reading file contents.\n * @param {string} filePath The filename to read.\n * @returns {string} The file contents, with the BOM removed.\n * @private\n */\nfunction readFile(filePath) {\n return fs.readFileSync(filePath, \"utf8\").replace(/^\\ufeff/u, \"\");\n}\n\n/**\n * Loads a YAML configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadYAMLConfigFile(filePath) {\n debug(`Loading YAML config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n\n // empty YAML file can be null, so always use\n return yaml.load(readFile(filePath)) || {};\n } catch (e) {\n debug(`Error reading YAML file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JSON configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSONConfigFile(filePath) {\n debug(`Loading JSON config file: ${filePath}`);\n\n try {\n return JSON.parse(stripComments(readFile(filePath)));\n } catch (e) {\n debug(`Error reading JSON file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n e.messageTemplate = \"failed-to-read-json\";\n e.messageData = {\n path: filePath,\n message: e.message\n };\n throw e;\n }\n}\n\n/**\n * Loads a legacy (.eslintrc) configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadLegacyConfigFile(filePath) {\n debug(`Loading legacy config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n return yaml.load(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};\n } catch (e) {\n debug(\"Error reading YAML file: %s\\n%o\", filePath, e);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JavaScript configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSConfigFile(filePath) {\n debug(`Loading JS config file: ${filePath}`);\n try {\n return importFresh(filePath);\n } catch (e) {\n debug(`Error reading JavaScript file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a configuration from a package.json file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadPackageJSONConfigFile(filePath) {\n debug(`Loading package.json config file: ${filePath}`);\n try {\n const packageData = loadJSONConfigFile(filePath);\n\n if (!Object.hasOwnProperty.call(packageData, \"eslintConfig\")) {\n throw Object.assign(\n new Error(\"package.json file doesn't have 'eslintConfig' field.\"),\n { code: \"ESLINT_CONFIG_FIELD_NOT_FOUND\" }\n );\n }\n\n return packageData.eslintConfig;\n } catch (e) {\n debug(`Error reading package.json file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a `.eslintignore` from a file.\n * @param {string} filePath The filename to load.\n * @returns {string[]} The ignore patterns from the file.\n * @private\n */\nfunction loadESLintIgnoreFile(filePath) {\n debug(`Loading .eslintignore file: ${filePath}`);\n\n try {\n return readFile(filePath)\n .split(/\\r?\\n/gu)\n .filter(line => line.trim() !== \"\" && !line.startsWith(\"#\"));\n } catch (e) {\n debug(`Error reading .eslintignore file: ${filePath}`);\n e.message = `Cannot read .eslintignore file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Creates an error to notify about a missing config to extend from.\n * @param {string} configName The name of the missing config.\n * @param {string} importerName The name of the config that imported the missing config\n * @param {string} messageTemplate The text template to source error strings from.\n * @returns {Error} The error object to throw\n * @private\n */\nfunction configInvalidError(configName, importerName, messageTemplate) {\n return Object.assign(\n new Error(`Failed to load config \"${configName}\" to extend from.`),\n {\n messageTemplate,\n messageData: { configName, importerName }\n }\n );\n}\n\n/**\n * Loads a configuration file regardless of the source. Inspects the file path\n * to determine the correctly way to load the config file.\n * @param {string} filePath The path to the configuration.\n * @returns {ConfigData|null} The configuration information.\n * @private\n */\nfunction loadConfigFile(filePath) {\n switch (path.extname(filePath)) {\n case \".js\":\n case \".cjs\":\n return loadJSConfigFile(filePath);\n\n case \".json\":\n if (path.basename(filePath) === \"package.json\") {\n return loadPackageJSONConfigFile(filePath);\n }\n return loadJSONConfigFile(filePath);\n\n case \".yaml\":\n case \".yml\":\n return loadYAMLConfigFile(filePath);\n\n default:\n return loadLegacyConfigFile(filePath);\n }\n}\n\n/**\n * Write debug log.\n * @param {string} request The requested module name.\n * @param {string} relativeTo The file path to resolve the request relative to.\n * @param {string} filePath The resolved file path.\n * @returns {void}\n */\nfunction writeDebugLogForLoading(request, relativeTo, filePath) {\n /* istanbul ignore next */\n if (debug.enabled) {\n let nameAndVersion = null;\n\n try {\n const packageJsonPath = ModuleResolver.resolve(\n `${request}/package.json`,\n relativeTo\n );\n const { version = \"unknown\" } = require(packageJsonPath);\n\n nameAndVersion = `${request}@${version}`;\n } catch (error) {\n debug(\"package.json was not found:\", error.message);\n nameAndVersion = request;\n }\n\n debug(\"Loaded: %s (%s)\", nameAndVersion, filePath);\n }\n}\n\n/**\n * Create a new context with default values.\n * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.\n * @param {\"config\" | \"ignore\" | \"implicit-processor\" | undefined} providedType The type of the current configuration. Default is `\"config\"`.\n * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.\n * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.\n * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.\n * @returns {ConfigArrayFactoryLoadingContext} The created context.\n */\nfunction createContext(\n { cwd, resolvePluginsRelativeTo },\n providedType,\n providedName,\n providedFilePath,\n providedMatchBasePath\n) {\n const filePath = providedFilePath\n ? path.resolve(cwd, providedFilePath)\n : \"\";\n const matchBasePath =\n (providedMatchBasePath && path.resolve(cwd, providedMatchBasePath)) ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const name =\n providedName ||\n (filePath && path.relative(cwd, filePath)) ||\n \"\";\n const pluginBasePath =\n resolvePluginsRelativeTo ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const type = providedType || \"config\";\n\n return { filePath, matchBasePath, name, pluginBasePath, type };\n}\n\n/**\n * Normalize a given plugin.\n * - Ensure the object to have four properties: configs, environments, processors, and rules.\n * - Ensure the object to not have other properties.\n * @param {Plugin} plugin The plugin to normalize.\n * @returns {Plugin} The normalized plugin.\n */\nfunction normalizePlugin(plugin) {\n\n // first check the cache\n let normalizedPlugin = normalizedPlugins.get(plugin);\n\n if (normalizedPlugin) {\n return normalizedPlugin;\n }\n\n normalizedPlugin = {\n configs: plugin.configs || {},\n environments: plugin.environments || {},\n processors: plugin.processors || {},\n rules: plugin.rules || {}\n };\n\n // save the reference for later\n normalizedPlugins.set(plugin, normalizedPlugin);\n\n return normalizedPlugin;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The factory of `ConfigArray` objects.\n */\nclass ConfigArrayFactory {\n\n /**\n * Initialize this instance.\n * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.\n */\n constructor({\n additionalPluginPool = new Map(),\n cwd = process.cwd(),\n resolvePluginsRelativeTo,\n builtInRules,\n resolver = ModuleResolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = {}) {\n internalSlotsMap.set(this, {\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo:\n resolvePluginsRelativeTo &&\n path.resolve(cwd, resolvePluginsRelativeTo),\n builtInRules,\n resolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n });\n }\n\n /**\n * Create `ConfigArray` instance from a config data.\n * @param {ConfigData|null} configData The config data to create.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.filePath] The path to this config data.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n create(configData, { basePath, filePath, name } = {}) {\n if (!configData) {\n return new ConfigArray();\n }\n\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n const elements = this._normalizeConfigData(configData, ctx);\n\n return new ConfigArray(...elements);\n }\n\n /**\n * Load a config file.\n * @param {string} filePath The path to a config file.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n loadFile(filePath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n\n return new ConfigArray(...this._loadConfigData(ctx));\n }\n\n /**\n * Load the config file on a given directory if exists.\n * @param {string} directoryPath The path to a directory.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadInDirectory(directoryPath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n\n for (const filename of configFilenames) {\n const ctx = createContext(\n slots,\n \"config\",\n name,\n path.join(directoryPath, filename),\n basePath\n );\n\n if (fs.existsSync(ctx.filePath) && fs.statSync(ctx.filePath).isFile()) {\n let configData;\n\n try {\n configData = loadConfigFile(ctx.filePath);\n } catch (error) {\n if (!error || error.code !== \"ESLINT_CONFIG_FIELD_NOT_FOUND\") {\n throw error;\n }\n }\n\n if (configData) {\n debug(`Config file found: ${ctx.filePath}`);\n return new ConfigArray(\n ...this._normalizeConfigData(configData, ctx)\n );\n }\n }\n }\n\n debug(`Config file not found on ${directoryPath}`);\n return new ConfigArray();\n }\n\n /**\n * Check if a config file on a given directory exists or not.\n * @param {string} directoryPath The path to a directory.\n * @returns {string | null} The path to the found config file. If not found then null.\n */\n static getPathToConfigFileInDirectory(directoryPath) {\n for (const filename of configFilenames) {\n const filePath = path.join(directoryPath, filename);\n\n if (fs.existsSync(filePath)) {\n if (filename === \"package.json\") {\n try {\n loadPackageJSONConfigFile(filePath);\n return filePath;\n } catch { /* ignore */ }\n } else {\n return filePath;\n }\n }\n }\n return null;\n }\n\n /**\n * Load `.eslintignore` file.\n * @param {string} filePath The path to a `.eslintignore` file to load.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadESLintIgnore(filePath) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(\n slots,\n \"ignore\",\n void 0,\n filePath,\n slots.cwd\n );\n const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)\n );\n }\n\n /**\n * Load `.eslintignore` file in the current working directory.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadDefaultESLintIgnore() {\n const slots = internalSlotsMap.get(this);\n const eslintIgnorePath = path.resolve(slots.cwd, \".eslintignore\");\n const packageJsonPath = path.resolve(slots.cwd, \"package.json\");\n\n if (fs.existsSync(eslintIgnorePath)) {\n return this.loadESLintIgnore(eslintIgnorePath);\n }\n if (fs.existsSync(packageJsonPath)) {\n const data = loadJSONConfigFile(packageJsonPath);\n\n if (Object.hasOwnProperty.call(data, \"eslintIgnore\")) {\n if (!Array.isArray(data.eslintIgnore)) {\n throw new Error(\"Package.json eslintIgnore property requires an array of paths\");\n }\n const ctx = createContext(\n slots,\n \"ignore\",\n \"eslintIgnore in package.json\",\n packageJsonPath,\n slots.cwd\n );\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)\n );\n }\n }\n\n return new ConfigArray();\n }\n\n /**\n * Load a given config file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} Loaded config.\n * @private\n */\n _loadConfigData(ctx) {\n return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);\n }\n\n /**\n * Normalize a given `.eslintignore` data to config array elements.\n * @param {string[]} ignorePatterns The patterns to ignore files.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeESLintIgnoreData(ignorePatterns, ctx) {\n const elements = this._normalizeObjectConfigData(\n { ignorePatterns },\n ctx\n );\n\n // Set `ignorePattern.loose` flag for backward compatibility.\n for (const element of elements) {\n if (element.ignorePattern) {\n element.ignorePattern.loose = true;\n }\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _normalizeConfigData(configData, ctx) {\n const validator = new ConfigValidator();\n\n validator.validateConfigSchema(configData, ctx.name || ctx.filePath);\n return this._normalizeObjectConfigData(configData, ctx);\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData|OverrideConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigData(configData, ctx) {\n const { files, excludedFiles, ...configBody } = configData;\n const criteria = OverrideTester.create(\n files,\n excludedFiles,\n ctx.matchBasePath\n );\n const elements = this._normalizeObjectConfigDataBody(configBody, ctx);\n\n // Apply the criteria to every element.\n for (const element of elements) {\n\n /*\n * Merge the criteria.\n * This is for the `overrides` entries that came from the\n * configurations of `overrides[].extends`.\n */\n element.criteria = OverrideTester.and(criteria, element.criteria);\n\n /*\n * Remove `root` property to ignore `root` settings which came from\n * `extends` in `overrides`.\n */\n if (element.criteria) {\n element.root = void 0;\n }\n\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigDataBody(\n {\n env,\n extends: extend,\n globals,\n ignorePatterns,\n noInlineConfig,\n parser: parserName,\n parserOptions,\n plugins: pluginList,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings,\n overrides: overrideList = []\n },\n ctx\n ) {\n const extendList = Array.isArray(extend) ? extend : [extend];\n const ignorePattern = ignorePatterns && new IgnorePattern(\n Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],\n ctx.matchBasePath\n );\n\n // Flatten `extends`.\n for (const extendName of extendList.filter(Boolean)) {\n yield* this._loadExtends(extendName, ctx);\n }\n\n // Load parser & plugins.\n const parser = parserName && this._loadParser(parserName, ctx);\n const plugins = pluginList && this._loadPlugins(pluginList, ctx);\n\n // Yield pseudo config data for file extension processors.\n if (plugins) {\n yield* this._takeFileExtensionProcessors(plugins, ctx);\n }\n\n // Yield the config data except `extends` and `overrides`.\n yield {\n\n // Debug information.\n type: ctx.type,\n name: ctx.name,\n filePath: ctx.filePath,\n\n // Config data.\n criteria: null,\n env,\n globals,\n ignorePattern,\n noInlineConfig,\n parser,\n parserOptions,\n plugins,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings\n };\n\n // Flatten `overries`.\n for (let i = 0; i < overrideList.length; ++i) {\n yield* this._normalizeObjectConfigData(\n overrideList[i],\n { ...ctx, name: `${ctx.name}#overrides[${i}]` }\n );\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtends(extendName, ctx) {\n debug(\"Loading {extends:%j} relative to %s\", extendName, ctx.filePath);\n try {\n if (extendName.startsWith(\"eslint:\")) {\n return this._loadExtendedBuiltInConfig(extendName, ctx);\n }\n if (extendName.startsWith(\"plugin:\")) {\n return this._loadExtendedPluginConfig(extendName, ctx);\n }\n return this._loadExtendedShareableConfig(extendName, ctx);\n } catch (error) {\n error.message += `\\nReferenced from: ${ctx.filePath || ctx.name}`;\n throw error;\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedBuiltInConfig(extendName, ctx) {\n const {\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = internalSlotsMap.get(this);\n\n if (extendName === \"eslint:recommended\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintRecommendedConfig) {\n if (typeof getEslintRecommendedConfig !== \"function\") {\n throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);\n }\n return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintRecommendedPath\n });\n }\n if (extendName === \"eslint:all\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintAllConfig) {\n if (typeof getEslintAllConfig !== \"function\") {\n throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);\n }\n return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintAllPath\n });\n }\n\n throw configInvalidError(extendName, ctx.name, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedPluginConfig(extendName, ctx) {\n const slashIndex = extendName.lastIndexOf(\"/\");\n\n if (slashIndex === -1) {\n throw configInvalidError(extendName, ctx.filePath, \"plugin-invalid\");\n }\n\n const pluginName = extendName.slice(\"plugin:\".length, slashIndex);\n const configName = extendName.slice(slashIndex + 1);\n\n if (isFilePath(pluginName)) {\n throw new Error(\"'extends' cannot use a file path for plugins.\");\n }\n\n const plugin = this._loadPlugin(pluginName, ctx);\n const configData =\n plugin.definition &&\n plugin.definition.configs[configName];\n\n if (configData) {\n return this._normalizeConfigData(configData, {\n ...ctx,\n filePath: plugin.filePath || ctx.filePath,\n name: `${ctx.name} » plugin:${plugin.id}/${configName}`\n });\n }\n\n throw plugin.error || configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedShareableConfig(extendName, ctx) {\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n let request;\n\n if (isFilePath(extendName)) {\n request = extendName;\n } else if (extendName.startsWith(\".\")) {\n request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.\n } else {\n request = naming.normalizePackageName(\n extendName,\n \"eslint-config\"\n );\n }\n\n let filePath;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (error) {\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n throw configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n throw error;\n }\n\n writeDebugLogForLoading(request, relativeTo, filePath);\n return this._loadConfigData({\n ...ctx,\n filePath,\n name: `${ctx.name} » ${request}`\n });\n }\n\n /**\n * Load given plugins.\n * @param {string[]} names The plugin names to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {Record} The loaded parser.\n * @private\n */\n _loadPlugins(names, ctx) {\n return names.reduce((map, name) => {\n if (isFilePath(name)) {\n throw new Error(\"Plugins array cannot includes file paths.\");\n }\n const plugin = this._loadPlugin(name, ctx);\n\n map[plugin.id] = plugin;\n\n return map;\n }, {});\n }\n\n /**\n * Load a given parser.\n * @param {string} nameOrPath The package name or the path to a parser file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentParser} The loaded parser.\n */\n _loadParser(nameOrPath, ctx) {\n debug(\"Loading parser %j from %s\", nameOrPath, ctx.filePath);\n\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n\n try {\n const filePath = resolver.resolve(nameOrPath, relativeTo);\n\n writeDebugLogForLoading(nameOrPath, relativeTo, filePath);\n\n return new ConfigDependency({\n definition: require(filePath),\n filePath,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (error) {\n\n // If the parser name is \"espree\", load the espree of ESLint.\n if (nameOrPath === \"espree\") {\n debug(\"Fallback espree.\");\n return new ConfigDependency({\n definition: require(\"espree\"),\n filePath: require.resolve(\"espree\"),\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n debug(\"Failed to load parser '%s' declared in '%s'.\", nameOrPath, ctx.name);\n error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;\n\n return new ConfigDependency({\n error,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n }\n\n /**\n * Load a given plugin.\n * @param {string} name The plugin name to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentPlugin} The loaded plugin.\n * @private\n */\n _loadPlugin(name, ctx) {\n debug(\"Loading plugin %j from %s\", name, ctx.filePath);\n\n const { additionalPluginPool, resolver } = internalSlotsMap.get(this);\n const request = naming.normalizePackageName(name, \"eslint-plugin\");\n const id = naming.getShorthandName(request, \"eslint-plugin\");\n const relativeTo = path.join(ctx.pluginBasePath, \"__placeholder__.js\");\n\n if (name.match(/\\s+/u)) {\n const error = Object.assign(\n new Error(`Whitespace found in plugin name '${name}'`),\n {\n messageTemplate: \"whitespace-found\",\n messageData: { pluginName: request }\n }\n );\n\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n // Check for additional pool.\n const plugin =\n additionalPluginPool.get(request) ||\n additionalPluginPool.get(id);\n\n if (plugin) {\n return new ConfigDependency({\n definition: normalizePlugin(plugin),\n filePath: \"\", // It's unknown where the plugin came from.\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n let filePath;\n let error;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (resolveError) {\n error = resolveError;\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n error.messageTemplate = \"plugin-missing\";\n error.messageData = {\n pluginName: request,\n resolvePluginsRelativeTo: ctx.pluginBasePath,\n importerName: ctx.name\n };\n }\n }\n\n if (filePath) {\n try {\n writeDebugLogForLoading(request, relativeTo, filePath);\n\n const startTime = Date.now();\n const pluginDefinition = require(filePath);\n\n debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);\n\n return new ConfigDependency({\n definition: normalizePlugin(pluginDefinition),\n filePath,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (loadError) {\n error = loadError;\n }\n }\n\n debug(\"Failed to load plugin '%s' declared in '%s'.\", name, ctx.name);\n error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n /**\n * Take file expression processors as config array elements.\n * @param {Record} plugins The plugin definitions.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The config array elements of file expression processors.\n * @private\n */\n *_takeFileExtensionProcessors(plugins, ctx) {\n for (const pluginId of Object.keys(plugins)) {\n const processors =\n plugins[pluginId] &&\n plugins[pluginId].definition &&\n plugins[pluginId].definition.processors;\n\n if (!processors) {\n continue;\n }\n\n for (const processorId of Object.keys(processors)) {\n if (processorId.startsWith(\".\")) {\n yield* this._normalizeObjectConfigData(\n {\n files: [`*${processorId}`],\n processor: `${pluginId}/${processorId}`\n },\n {\n ...ctx,\n type: \"implicit-processor\",\n name: `${ctx.name}#processors[\"${pluginId}/${processorId}\"]`\n }\n );\n }\n }\n }\n }\n}\n\nexport { ConfigArrayFactory, createContext };\n","/**\n * @fileoverview `CascadingConfigArrayFactory` class.\n *\n * `CascadingConfigArrayFactory` class has a responsibility:\n *\n * 1. Handles cascading of config files.\n *\n * It provides two methods:\n *\n * - `getConfigArrayForFile(filePath)`\n * Get the corresponded configuration of a given file. This method doesn't\n * throw even if the given file didn't exist.\n * - `clearCache()`\n * Clear the internal cache. You have to call this method when\n * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends\n * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport { emitDeprecationWarning } from \"./shared/deprecation-warnings.js\";\n\nconst debug = debugOrig(\"eslintrc:cascading-config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {ReturnType} ConfigArray */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {ConfigData} [baseConfig] The config by `baseConfig` option.\n * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.\n * @property {string} [cwd] The base directory to start lookup.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]} [rulePaths] The value of `--rulesdir` option.\n * @property {string} [specificConfigPath] The value of `--config` option.\n * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryInternalSlots\n * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.\n * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.\n * @property {ConfigArray} cliConfigArray The config array of CLI options.\n * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.\n * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.\n * @property {Map} configCache The cache from directory paths to config arrays.\n * @property {string} cwd The base directory to start lookup.\n * @property {WeakMap} finalizeCache The cache from config arrays to finalized config arrays.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.\n * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.\n * @property {boolean} useEslintrc if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Create the config array from `baseConfig` and `rulePaths`.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createBaseConfigArray({\n configArrayFactory,\n baseConfigData,\n rulePaths,\n cwd,\n loadRules\n}) {\n const baseConfigArray = configArrayFactory.create(\n baseConfigData,\n { name: \"BaseConfig\" }\n );\n\n /*\n * Create the config array element for the default ignore patterns.\n * This element has `ignorePattern` property that ignores the default\n * patterns in the current working directory.\n */\n baseConfigArray.unshift(configArrayFactory.create(\n { ignorePatterns: IgnorePattern.DefaultPatterns },\n { name: \"DefaultIgnorePattern\" }\n )[0]);\n\n /*\n * Load rules `--rulesdir` option as a pseudo plugin.\n * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate\n * the rule's options with only information in the config array.\n */\n if (rulePaths && rulePaths.length > 0) {\n baseConfigArray.push({\n type: \"config\",\n name: \"--rulesdir\",\n filePath: \"\",\n plugins: {\n \"\": new ConfigDependency({\n definition: {\n rules: rulePaths.reduce(\n (map, rulesPath) => Object.assign(\n map,\n loadRules(rulesPath, cwd)\n ),\n {}\n )\n },\n filePath: \"\",\n id: \"\",\n importerName: \"--rulesdir\",\n importerPath: \"\"\n })\n }\n });\n }\n\n return baseConfigArray;\n}\n\n/**\n * Create the config array from CLI options.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n}) {\n const cliConfigArray = configArrayFactory.create(\n cliConfigData,\n { name: \"CLIOptions\" }\n );\n\n cliConfigArray.unshift(\n ...(ignorePath\n ? configArrayFactory.loadESLintIgnore(ignorePath)\n : configArrayFactory.loadDefaultESLintIgnore())\n );\n\n if (specificConfigPath) {\n cliConfigArray.unshift(\n ...configArrayFactory.loadFile(\n specificConfigPath,\n { name: \"--config\", basePath: cwd }\n )\n );\n }\n\n return cliConfigArray;\n}\n\n/**\n * The error type when there are files matched by a glob, but all of them have been ignored.\n */\nclass ConfigurationNotFoundError extends Error {\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @param {string} directoryPath The directory path.\n */\n constructor(directoryPath) {\n super(`No ESLint configuration found in ${directoryPath}.`);\n this.messageTemplate = \"no-config-found\";\n this.messageData = { directoryPath };\n }\n}\n\n/**\n * This class provides the functionality that enumerates every file which is\n * matched by given glob patterns and that configuration.\n */\nclass CascadingConfigArrayFactory {\n\n /**\n * Initialize this enumerator.\n * @param {CascadingConfigArrayFactoryOptions} options The options.\n */\n constructor({\n additionalPluginPool = new Map(),\n baseConfig: baseConfigData = null,\n cliConfig: cliConfigData = null,\n cwd = process.cwd(),\n ignorePath,\n resolvePluginsRelativeTo,\n rulePaths = [],\n specificConfigPath = null,\n useEslintrc = true,\n builtInRules = new Map(),\n loadRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n } = {}) {\n const configArrayFactory = new ConfigArrayFactory({\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo,\n builtInRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n });\n\n internalSlotsMap.set(this, {\n baseConfigArray: createBaseConfigArray({\n baseConfigData,\n configArrayFactory,\n cwd,\n rulePaths,\n loadRules\n }),\n baseConfigData,\n cliConfigArray: createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n }),\n cliConfigData,\n configArrayFactory,\n configCache: new Map(),\n cwd,\n finalizeCache: new WeakMap(),\n ignorePath,\n rulePaths,\n specificConfigPath,\n useEslintrc,\n builtInRules,\n loadRules\n });\n }\n\n /**\n * The path to the current working directory.\n * This is used by tests.\n * @type {string}\n */\n get cwd() {\n const { cwd } = internalSlotsMap.get(this);\n\n return cwd;\n }\n\n /**\n * Get the config array of a given file.\n * If `filePath` was not given, it returns the config which contains only\n * `baseConfigData` and `cliConfigData`.\n * @param {string} [filePath] The file path to a file.\n * @param {Object} [options] The options.\n * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The config array of the file.\n */\n getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {\n const {\n baseConfigArray,\n cliConfigArray,\n cwd\n } = internalSlotsMap.get(this);\n\n if (!filePath) {\n return new ConfigArray(...baseConfigArray, ...cliConfigArray);\n }\n\n const directoryPath = path.dirname(path.resolve(cwd, filePath));\n\n debug(`Load config files for ${directoryPath}.`);\n\n return this._finalizeConfigArray(\n this._loadConfigInAncestors(directoryPath),\n directoryPath,\n ignoreNotFoundError\n );\n }\n\n /**\n * Set the config data to override all configs.\n * Require to call `clearCache()` method after this method is called.\n * @param {ConfigData} configData The config data to override all configs.\n * @returns {void}\n */\n setOverrideConfig(configData) {\n const slots = internalSlotsMap.get(this);\n\n slots.cliConfigData = configData;\n }\n\n /**\n * Clear config cache.\n * @returns {void}\n */\n clearCache() {\n const slots = internalSlotsMap.get(this);\n\n slots.baseConfigArray = createBaseConfigArray(slots);\n slots.cliConfigArray = createCLIConfigArray(slots);\n slots.configCache.clear();\n }\n\n /**\n * Load and normalize config files from the ancestor directories.\n * @param {string} directoryPath The path to a leaf directory.\n * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {\n const {\n baseConfigArray,\n configArrayFactory,\n configCache,\n cwd,\n useEslintrc\n } = internalSlotsMap.get(this);\n\n if (!useEslintrc) {\n return baseConfigArray;\n }\n\n let configArray = configCache.get(directoryPath);\n\n // Hit cache.\n if (configArray) {\n debug(`Cache hit: ${directoryPath}.`);\n return configArray;\n }\n debug(`No cache found: ${directoryPath}.`);\n\n const homePath = os.homedir();\n\n // Consider this is root.\n if (directoryPath === homePath && cwd !== homePath) {\n debug(\"Stop traversing because of considered root.\");\n if (configsExistInSubdirs) {\n const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);\n\n if (filePath) {\n emitDeprecationWarning(\n filePath,\n \"ESLINT_PERSONAL_CONFIG_SUPPRESS\"\n );\n }\n }\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n\n // Load the config on this directory.\n try {\n configArray = configArrayFactory.loadInDirectory(directoryPath);\n } catch (error) {\n /* istanbul ignore next */\n if (error.code === \"EACCES\") {\n debug(\"Stop traversing because of 'EACCES' error.\");\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n throw error;\n }\n\n if (configArray.length > 0 && configArray.isRoot()) {\n debug(\"Stop traversing because of 'root:true'.\");\n configArray.unshift(...baseConfigArray);\n return this._cacheConfig(directoryPath, configArray);\n }\n\n // Load from the ancestors and merge it.\n const parentPath = path.dirname(directoryPath);\n const parentConfigArray = parentPath && parentPath !== directoryPath\n ? this._loadConfigInAncestors(\n parentPath,\n configsExistInSubdirs || configArray.length > 0\n )\n : baseConfigArray;\n\n if (configArray.length > 0) {\n configArray.unshift(...parentConfigArray);\n } else {\n configArray = parentConfigArray;\n }\n\n // Cache and return.\n return this._cacheConfig(directoryPath, configArray);\n }\n\n /**\n * Freeze and cache a given config.\n * @param {string} directoryPath The path to a directory as a cache key.\n * @param {ConfigArray} configArray The config array as a cache value.\n * @returns {ConfigArray} The `configArray` (frozen).\n */\n _cacheConfig(directoryPath, configArray) {\n const { configCache } = internalSlotsMap.get(this);\n\n Object.freeze(configArray);\n configCache.set(directoryPath, configArray);\n\n return configArray;\n }\n\n /**\n * Finalize a given config array.\n * Concatenate `--config` and other CLI options.\n * @param {ConfigArray} configArray The parent config array.\n * @param {string} directoryPath The path to the leaf directory to find config files.\n * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {\n const {\n cliConfigArray,\n configArrayFactory,\n finalizeCache,\n useEslintrc,\n builtInRules\n } = internalSlotsMap.get(this);\n\n let finalConfigArray = finalizeCache.get(configArray);\n\n if (!finalConfigArray) {\n finalConfigArray = configArray;\n\n // Load the personal config if there are no regular config files.\n if (\n useEslintrc &&\n configArray.every(c => !c.filePath) &&\n cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.\n ) {\n const homePath = os.homedir();\n\n debug(\"Loading the config file of the home directory:\", homePath);\n\n const personalConfigArray = configArrayFactory.loadInDirectory(\n homePath,\n { name: \"PersonalConfig\" }\n );\n\n if (\n personalConfigArray.length > 0 &&\n !directoryPath.startsWith(homePath)\n ) {\n const lastElement =\n personalConfigArray[personalConfigArray.length - 1];\n\n emitDeprecationWarning(\n lastElement.filePath,\n \"ESLINT_PERSONAL_CONFIG_LOAD\"\n );\n }\n\n finalConfigArray = finalConfigArray.concat(personalConfigArray);\n }\n\n // Apply CLI options.\n if (cliConfigArray.length > 0) {\n finalConfigArray = finalConfigArray.concat(cliConfigArray);\n }\n\n // Validate rule settings and environments.\n const validator = new ConfigValidator({\n builtInRules\n });\n\n validator.validateConfigArray(finalConfigArray);\n\n // Cache it.\n Object.freeze(finalConfigArray);\n finalizeCache.set(configArray, finalConfigArray);\n\n debug(\n \"Configuration was determined: %o on %s\",\n finalConfigArray,\n directoryPath\n );\n }\n\n // At least one element (the default ignore patterns) exists.\n if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {\n throw new ConfigurationNotFoundError(directoryPath);\n }\n\n return finalConfigArray;\n }\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport { CascadingConfigArrayFactory };\n","/**\n * @fileoverview Compatibility class for flat config.\n * @author Nicholas C. Zakas\n */\n\n//-----------------------------------------------------------------------------\n// Requirements\n//-----------------------------------------------------------------------------\n\nimport createDebug from \"debug\";\nimport path from \"path\";\n\nimport environments from \"../conf/environments.js\";\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n\nconst debug = createDebug(\"eslintrc:flat-compat\");\nconst cafactory = Symbol(\"cafactory\");\n\n/**\n * Translates an ESLintRC-style config object into a flag-config-style config\n * object.\n * @param {Object} eslintrcConfig An ESLintRC-style config object.\n * @param {Object} options Options to help translate the config.\n * @param {string} options.resolveConfigRelativeTo To the directory to resolve\n * configs from.\n * @param {string} options.resolvePluginsRelativeTo The directory to resolve\n * plugins from.\n * @param {ReadOnlyMap} options.pluginEnvironments A map of plugin environment\n * names to objects.\n * @param {ReadOnlyMap} options.pluginProcessors A map of plugin processor\n * names to objects.\n * @returns {Object} A flag-config-style config object.\n */\nfunction translateESLintRC(eslintrcConfig, {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo,\n pluginEnvironments,\n pluginProcessors\n}) {\n\n const flatConfig = {};\n const configs = [];\n const languageOptions = {};\n const linterOptions = {};\n const keysToCopy = [\"settings\", \"rules\", \"processor\"];\n const languageOptionsKeysToCopy = [\"globals\", \"parser\", \"parserOptions\"];\n const linterOptionsKeysToCopy = [\"noInlineConfig\", \"reportUnusedDisableDirectives\"];\n\n // copy over simple translations\n for (const key of keysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig[key] = eslintrcConfig[key];\n }\n }\n\n // copy over languageOptions\n for (const key of languageOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n\n // create the languageOptions key in the flat config\n flatConfig.languageOptions = languageOptions;\n\n if (key === \"parser\") {\n debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);\n\n if (eslintrcConfig[key].error) {\n throw eslintrcConfig[key].error;\n }\n\n languageOptions[key] = eslintrcConfig[key].definition;\n continue;\n }\n\n // clone any object values that are in the eslintrc config\n if (eslintrcConfig[key] && typeof eslintrcConfig[key] === \"object\") {\n languageOptions[key] = {\n ...eslintrcConfig[key]\n };\n } else {\n languageOptions[key] = eslintrcConfig[key];\n }\n }\n }\n\n // copy over linterOptions\n for (const key of linterOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig.linterOptions = linterOptions;\n linterOptions[key] = eslintrcConfig[key];\n }\n }\n\n // move ecmaVersion a level up\n if (languageOptions.parserOptions) {\n\n if (\"ecmaVersion\" in languageOptions.parserOptions) {\n languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;\n delete languageOptions.parserOptions.ecmaVersion;\n }\n\n if (\"sourceType\" in languageOptions.parserOptions) {\n languageOptions.sourceType = languageOptions.parserOptions.sourceType;\n delete languageOptions.parserOptions.sourceType;\n }\n\n // check to see if we even need parserOptions anymore and remove it if not\n if (Object.keys(languageOptions.parserOptions).length === 0) {\n delete languageOptions.parserOptions;\n }\n }\n\n // overrides\n if (eslintrcConfig.criteria) {\n flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];\n }\n\n // translate plugins\n if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === \"object\") {\n debug(`Translating plugins: ${eslintrcConfig.plugins}`);\n\n flatConfig.plugins = {};\n\n for (const pluginName of Object.keys(eslintrcConfig.plugins)) {\n\n debug(`Translating plugin: ${pluginName}`);\n debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);\n\n const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];\n\n if (error) {\n throw error;\n }\n\n flatConfig.plugins[pluginName] = plugin;\n\n // create a config for any processors\n if (plugin.processors) {\n for (const processorName of Object.keys(plugin.processors)) {\n if (processorName.startsWith(\".\")) {\n debug(`Assigning processor: ${pluginName}/${processorName}`);\n\n configs.unshift({\n files: [`**/*${processorName}`],\n processor: pluginProcessors.get(`${pluginName}/${processorName}`)\n });\n }\n\n }\n }\n }\n }\n\n // translate env - must come after plugins\n if (eslintrcConfig.env && typeof eslintrcConfig.env === \"object\") {\n for (const envName of Object.keys(eslintrcConfig.env)) {\n\n // only add environments that are true\n if (eslintrcConfig.env[envName]) {\n debug(`Translating environment: ${envName}`);\n\n if (environments.has(envName)) {\n\n // built-in environments should be defined first\n configs.unshift(...translateESLintRC(environments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n } else if (pluginEnvironments.has(envName)) {\n\n // if the environment comes from a plugin, it should come after the plugin config\n configs.push(...translateESLintRC(pluginEnvironments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n }\n }\n }\n }\n\n // only add if there are actually keys in the config\n if (Object.keys(flatConfig).length > 0) {\n configs.push(flatConfig);\n }\n\n return configs;\n}\n\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\n/**\n * A compatibility class for working with configs.\n */\nclass FlatCompat {\n\n constructor({\n baseDirectory = process.cwd(),\n resolvePluginsRelativeTo = baseDirectory,\n recommendedConfig,\n allConfig\n } = {}) {\n this.baseDirectory = baseDirectory;\n this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;\n this[cafactory] = new ConfigArrayFactory({\n cwd: baseDirectory,\n resolvePluginsRelativeTo,\n getEslintAllConfig: () => {\n\n if (!allConfig) {\n throw new TypeError(\"Missing parameter 'allConfig' in FlatCompat constructor.\");\n }\n\n return allConfig;\n },\n getEslintRecommendedConfig: () => {\n\n if (!recommendedConfig) {\n throw new TypeError(\"Missing parameter 'recommendedConfig' in FlatCompat constructor.\");\n }\n\n return recommendedConfig;\n }\n });\n }\n\n /**\n * Translates an ESLintRC-style config into a flag-config-style config.\n * @param {Object} eslintrcConfig The ESLintRC-style config object.\n * @returns {Object} A flag-config-style config object.\n */\n config(eslintrcConfig) {\n const eslintrcArray = this[cafactory].create(eslintrcConfig, {\n basePath: this.baseDirectory\n });\n\n const flatArray = [];\n let hasIgnorePatterns = false;\n\n eslintrcArray.forEach(configData => {\n if (configData.type === \"config\") {\n hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;\n flatArray.push(...translateESLintRC(configData, {\n resolveConfigRelativeTo: path.join(this.baseDirectory, \"__placeholder.js\"),\n resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, \"__placeholder.js\"),\n pluginEnvironments: eslintrcArray.pluginEnvironments,\n pluginProcessors: eslintrcArray.pluginProcessors\n }));\n }\n });\n\n // combine ignorePatterns to emulate ESLintRC behavior better\n if (hasIgnorePatterns) {\n flatArray.unshift({\n ignores: [filePath => {\n\n // Compute the final config for this file.\n // This filters config array elements by `files`/`excludedFiles` then merges the elements.\n const finalConfig = eslintrcArray.extractConfig(filePath);\n\n // Test the `ignorePattern` properties of the final config.\n return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);\n }]\n });\n }\n\n return flatArray;\n }\n\n /**\n * Translates the `env` section of an ESLintRC-style config.\n * @param {Object} envConfig The `env` section of an ESLintRC config.\n * @returns {Object[]} An array of flag-config objects representing the environments.\n */\n env(envConfig) {\n return this.config({\n env: envConfig\n });\n }\n\n /**\n * Translates the `extends` section of an ESLintRC-style config.\n * @param {...string} configsToExtend The names of the configs to load.\n * @returns {Object[]} An array of flag-config objects representing the config.\n */\n extends(...configsToExtend) {\n return this.config({\n extends: configsToExtend\n });\n }\n\n /**\n * Translates the `plugins` section of an ESLintRC-style config.\n * @param {...string} plugins The names of the plugins to load.\n * @returns {Object[]} An array of flag-config objects representing the plugins.\n */\n plugins(...plugins) {\n return this.config({\n plugins\n });\n }\n}\n\nexport { FlatCompat };\n","/**\n * @fileoverview Package exports for @eslint/eslintrc\n * @author Nicholas C. Zakas\n */\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport {\n ConfigArrayFactory,\n createContext as createConfigArrayFactoryContext\n} from \"./config-array-factory.js\";\n\nimport { CascadingConfigArrayFactory } from \"./cascading-config-array-factory.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array/index.js\";\nimport { ConfigDependency } from \"./config-array/config-dependency.js\";\nimport { ExtractedConfig } from \"./config-array/extracted-config.js\";\nimport { IgnorePattern } from \"./config-array/ignore-pattern.js\";\nimport { OverrideTester } from \"./config-array/override-tester.js\";\nimport * as ConfigOps from \"./shared/config-ops.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport { FlatCompat } from \"./flat-compat.js\";\nimport environments from \"../conf/environments.js\";\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nconst Legacy = {\n ConfigArray,\n createConfigArrayFactoryContext,\n CascadingConfigArrayFactory,\n ConfigArrayFactory,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs,\n environments,\n\n // shared\n ConfigOps,\n ConfigValidator,\n ModuleResolver,\n naming\n};\n\nexport {\n\n Legacy,\n\n FlatCompat\n\n};\n"],"names":["debug","debugOrig","path","ignore","assert","internalSlotsMap","util","minimatch","Ajv","globals","BuiltInEnvironments","ConfigOps.normalizeConfigGlobal","Module","require","createRequire","fs","stripComments","importFresh","ModuleResolver.resolve","naming.normalizePackageName","naming.getShorthandName","os","createDebug","createConfigArrayFactoryContext"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAUA;AACA,MAAMA,OAAK,GAAGC,6BAAS,CAAC,yBAAyB,CAAC,CAAC;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,CAAC,WAAW,EAAE;AAC5C,IAAI,IAAI,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AAChC;AACA,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACjD,QAAQ,MAAM,CAAC,GAAG,MAAM,CAAC;AACzB,QAAQ,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;AACjC;AACA;AACA,QAAQ,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7C;AACA;AACA,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AAC3E,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/B,gBAAgB,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AAChD,gBAAgB,MAAM;AACtB,aAAa;AACb,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,KAAKC,wBAAI,CAAC,GAAG,EAAE;AACnC,gBAAgB,UAAU,GAAG,CAAC,CAAC;AAC/B,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA,IAAI,IAAI,cAAc,GAAG,MAAM,IAAIA,wBAAI,CAAC,GAAG,CAAC;AAC5C;AACA;AACA,IAAI,IAAI,cAAc,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;AACxF,QAAQ,cAAc,IAAIA,wBAAI,CAAC,GAAG,CAAC;AACnC,KAAK;AACL,IAAI,OAAO,cAAc,CAAC;AAC1B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE;AAC5B,IAAI,MAAM,OAAO,GAAGA,wBAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC5C;AACA,IAAI,IAAIA,wBAAI,CAAC,GAAG,KAAK,GAAG,EAAE;AAC1B,QAAQ,OAAO,OAAO,CAAC;AACvB,KAAK;AACL,IAAI,OAAO,OAAO,CAAC,KAAK,CAACA,wBAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,QAAQ,EAAE;AAC7B,IAAI,MAAM,KAAK;AACf,QAAQ,QAAQ,CAAC,QAAQ,CAACA,wBAAI,CAAC,GAAG,CAAC;AACnC,SAAS,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAChE,KAAK,CAAC;AACN;AACA,IAAI,OAAO,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC;AAC5B,CAAC;AACD;AACA,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAClE;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC;AACpB;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,eAAe,GAAG;AACjC,QAAQ,OAAO,eAAe,CAAC;AAC/B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,mBAAmB,CAAC,GAAG,EAAE;AACpC,QAAQ,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,aAAa,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5E,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,YAAY,CAAC,cAAc,EAAE;AACxC,QAAQF,OAAK,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;AACjD;AACA,QAAQ,MAAM,QAAQ,GAAG,qBAAqB,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AACpF,QAAQ,MAAM,QAAQ,GAAG,EAAE,CAAC,MAAM;AAClC,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AACzE,SAAS,CAAC;AACV,QAAQ,MAAM,EAAE,GAAGG,0BAAM,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;AAC3F,QAAQ,MAAM,KAAK,GAAGA,0BAAM,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACzE;AACA,QAAQH,OAAK,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;AACzD;AACA,QAAQ,OAAO,MAAM,CAAC,MAAM;AAC5B,YAAY,CAAC,QAAQ,EAAE,GAAG,GAAG,KAAK,KAAK;AACvC,gBAAgBI,0BAAM,CAACF,wBAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,wCAAwC,CAAC,CAAC;AAC5F,gBAAgB,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAChE,gBAAgB,MAAM,OAAO,GAAG,UAAU,KAAK,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACjF,gBAAgB,MAAM,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,CAAC;AACnD,gBAAgB,MAAM,MAAM,GAAG,OAAO,KAAK,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AAC5E;AACA,gBAAgBF,OAAK,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACjF,gBAAgB,OAAO,MAAM,CAAC;AAC9B,aAAa;AACb,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAClC,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE;AACpC,QAAQI,0BAAM,CAACF,wBAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,wCAAwC,CAAC,CAAC;AACpF;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AAC3B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,WAAW,EAAE;AACvC,QAAQE,0BAAM,CAACF,wBAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,2CAA2C,CAAC,CAAC;AAC1F,QAAQ,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;AACnD;AACA,QAAQ,IAAI,WAAW,KAAK,QAAQ,EAAE;AACtC,YAAY,OAAO,QAAQ,CAAC;AAC5B,SAAS;AACT,QAAQ,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC7D;AACA,QAAQ,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,IAAI;AACvC,YAAY,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACrD,YAAY,MAAM,IAAI,GAAG,QAAQ,GAAG,GAAG,GAAG,EAAE,CAAC;AAC7C,YAAY,MAAM,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAC/D;AACA,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;AAChE,gBAAgB,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACjD,aAAa;AACb,YAAY,OAAO,KAAK,GAAG,OAAO,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACnE,SAAS,CAAC,CAAC;AACX,KAAK;AACL;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE;AAC5B,IAAI,OAAO,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AACD;AACA;AACA;AACA;AACA,MAAM,eAAe,CAAC;AACtB,IAAI,WAAW,GAAG;AAClB;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,0BAA0B,GAAG,EAAE,CAAC;AAC7C;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;AACtB;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;AAC1B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC;AAC9B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,CAAC;AACrC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;AAC3B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;AAChC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;AAC1B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;AAC9B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,6BAA6B,GAAG,KAAK,CAAC,CAAC;AACpD;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;AAC3B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,qCAAqC,GAAG;AAC5C,QAAQ,MAAM;AACd;AACA,YAAY,0BAA0B,EAAE,QAAQ;AAChD,YAAY,SAAS,EAAE,QAAQ;AAC/B;AACA,YAAY,OAAO;AACnB,YAAY,GAAG,MAAM;AACrB,SAAS,GAAG,IAAI,CAAC;AACjB;AACA,QAAQ,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAChE,QAAQ,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;AAC/E,QAAQ,MAAM,CAAC,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAC;AAChE;AACA;AACA,QAAQ,IAAI,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,eAAe,CAAC,EAAE;AAC9E,YAAY,MAAM,CAAC,cAAc;AACjC,gBAAgB,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AAClF,SAAS;AACT;AACA,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;;AC9IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMG,kBAAgB,GAAG,IAAI,cAAc,OAAO,CAAC;AACnD,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAQ,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACnC;AACA,QAAQ,IAAI,CAAC,KAAK,EAAE;AACpB,YAAY,KAAK,GAAG;AACpB,gBAAgB,KAAK,EAAE,IAAI,GAAG,EAAE;AAChC,gBAAgB,MAAM,EAAE,IAAI;AAC5B,gBAAgB,YAAY,EAAE,IAAI;AAClC,gBAAgB,OAAO,EAAE,IAAI;AAC7B,aAAa,CAAC;AACd,YAAY,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAClC,SAAS;AACT;AACA,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL,CAAC,EAAE,CAAC;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE;AAC/C,IAAI,MAAM,OAAO,GAAG,EAAE,CAAC;AACvB;AACA,IAAI,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE;AACnD,QAAQ,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpC;AACA,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE;AAChF,YAAY,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,SAAS;AACT,KAAK;AACL;AACA,IAAI,OAAO,OAAO,CAAC;AACnB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,CAAC,EAAE;AAC5B,IAAI,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC;AAC/C,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE;AAC/C,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;AAClC,QAAQ,OAAO;AACf,KAAK;AACL;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AAC3C,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE;AACjC,YAAY,SAAS;AACrB,SAAS;AACT;AACA,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;AAC1C,YAAY,qBAAqB,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5D,SAAS,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE;AAC3C,YAAY,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;AAC9C,gBAAgB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;AACnE,gBAAgB,qBAAqB,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAChE,aAAa,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE;AAC/C,gBAAgB,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1C,aAAa;AACb,SAAS;AACT,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA,MAAM,mBAAmB,SAAS,KAAK,CAAC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE;AACnC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvH,QAAQ,IAAI,CAAC,eAAe,GAAG,iBAAiB,CAAC;AACjD,QAAQ,IAAI,CAAC,WAAW,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACjD,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE;AACtC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;AAClC,QAAQ,OAAO;AACf,KAAK;AACL;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AAC3C,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE;AACjC,YAAY,SAAS;AACrB,SAAS;AACT,QAAQ,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AACxC,QAAQ,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AACxC;AACA;AACA,QAAQ,IAAI,WAAW,KAAK,KAAK,CAAC,EAAE;AACpC,YAAY,IAAI,WAAW,CAAC,KAAK,EAAE;AACnC,gBAAgB,MAAM,WAAW,CAAC,KAAK,CAAC;AACxC,aAAa;AACb,YAAY,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;AACtC,SAAS,MAAM,IAAI,WAAW,CAAC,QAAQ,KAAK,WAAW,CAAC,QAAQ,EAAE;AAClE,YAAY,MAAM,IAAI,mBAAmB,CAAC,GAAG,EAAE;AAC/C,gBAAgB;AAChB,oBAAoB,QAAQ,EAAE,WAAW,CAAC,QAAQ;AAClD,oBAAoB,YAAY,EAAE,WAAW,CAAC,YAAY;AAC1D,iBAAiB;AACjB,gBAAgB;AAChB,oBAAoB,QAAQ,EAAE,WAAW,CAAC,QAAQ;AAClD,oBAAoB,YAAY,EAAE,WAAW,CAAC,YAAY;AAC1D,iBAAiB;AACjB,aAAa,CAAC,CAAC;AACf,SAAS;AACT,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE;AAC1C,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;AAClC,QAAQ,OAAO;AACf,KAAK;AACL;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AAC3C,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE;AACjC,YAAY,SAAS;AACrB,SAAS;AACT,QAAQ,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AACtC,QAAQ,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AACtC;AACA;AACA,QAAQ,IAAI,SAAS,KAAK,KAAK,CAAC,EAAE;AAClC,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;AAC1C,gBAAgB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;AAC7C,aAAa,MAAM;AACnB,gBAAgB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC1C,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,SAAS,MAAM;AACf,YAAY,SAAS,CAAC,MAAM,KAAK,CAAC;AAClC,YAAY,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AACpC,YAAY,SAAS,CAAC,MAAM,IAAI,CAAC;AACjC,UAAU;AACV,YAAY,SAAS,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,SAAS;AACT,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE;AACzC,IAAI,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;AACzC,IAAI,MAAM,cAAc,GAAG,EAAE,CAAC;AAC9B;AACA;AACA,IAAI,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;AACjC,QAAQ,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE;AAC9C,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE;AACtC,gBAAgB,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AAC3C,aAAa;AACb,YAAY,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;AAC3C,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,EAAE;AACpD,YAAY,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;AACjD,SAAS;AACT;AACA;AACA,QAAQ,IAAI,MAAM,CAAC,cAAc,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,cAAc,KAAK,KAAK,CAAC,EAAE;AACnF,YAAY,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;AAC3D,YAAY,MAAM,CAAC,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;AAC7D,SAAS;AACT;AACA;AACA,QAAQ,IAAI,MAAM,CAAC,6BAA6B,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,6BAA6B,KAAK,KAAK,CAAC,EAAE;AACjH,YAAY,MAAM,CAAC,6BAA6B,GAAG,OAAO,CAAC,6BAA6B,CAAC;AACzF,SAAS;AACT;AACA;AACA,QAAQ,IAAI,OAAO,CAAC,aAAa,EAAE;AACnC,YAAY,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AACvD,SAAS;AACT;AACA;AACA,QAAQ,qBAAqB,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AACvD,QAAQ,qBAAqB,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;AAC/D,QAAQ,qBAAqB,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;AAC3E,QAAQ,qBAAqB,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;AACjE,QAAQ,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;AACtD,QAAQ,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;AACtD,KAAK;AACL;AACA;AACA,IAAI,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;AACnC,QAAQ,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9E,KAAK;AACL;AACA,IAAI,OAAO,MAAM,CAAC;AAClB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE;AACjD,IAAI,IAAI,IAAI,EAAE;AACd,QAAQ,MAAM,MAAM,GAAG,QAAQ,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClD;AACA,QAAQ,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AACzD,YAAY,GAAG,CAAC,GAAG;AACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AACjC,gBAAgB,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK;AACpD,aAAa,CAAC;AACd,SAAS;AACT,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,mBAAmB,CAAC,IAAI,EAAE;AACnC,IAAI,OAAO,OAAO,IAAI,KAAK,UAAU,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;AAChE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,CAAC,GAAG,EAAE;AACpC,IAAI,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE;AACjC,QAAQ,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;AACpD,QAAQ,MAAM,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;AACrD,QAAQ,GAAG,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE;AAClD,KAAK,CAAC,CAAC;AACP,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,QAAQ,EAAE,KAAK,EAAE;AAC/C,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;AAChC;AACA,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AAC7B,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;AACnC,IAAI,KAAK,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;AAC9B;AACA,IAAI,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AACpC,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;AAC9B,YAAY,SAAS;AACrB,SAAS;AACT;AACA,QAAQ,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACzE,YAAY,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;AAC5C;AACA,YAAY,IAAI,CAAC,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AACpD,gBAAgB,SAAS;AACzB,aAAa;AACb,YAAY,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACpC;AACA,YAAY,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;AACjE,YAAY,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;AACrE,YAAY,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AAChF,SAAS;AACT,KAAK;AACL;AACA,IAAI,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACxC,IAAI,qBAAqB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAC9C,IAAI,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,sBAAsB,CAAC,QAAQ,EAAE;AAC1C,IAAI,MAAM,KAAK,GAAGA,kBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACjD;AACA,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;AACxB,QAAQ,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9C,KAAK;AACL;AACA,IAAI,OAAO,KAAK,CAAC;AACjB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,WAAW,SAAS,KAAK,CAAC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,kBAAkB,GAAG;AAC7B,QAAQ,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AACnD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,gBAAgB,GAAG;AAC3B,QAAQ,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC;AACzD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,WAAW,GAAG;AACtB,QAAQ,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AACpD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE;AACnD,YAAY,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC;AACA,YAAY,IAAI,OAAO,IAAI,KAAK,SAAS,EAAE;AAC3C,gBAAgB,OAAO,IAAI,CAAC;AAC5B,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,QAAQ,EAAE;AAC5B,QAAQ,MAAM,EAAE,KAAK,EAAE,GAAGA,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrD,QAAQ,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1D,QAAQ,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AAClC,YAAY,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC7D,SAAS;AACT;AACA,QAAQ,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACnC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,sBAAsB,CAAC,QAAQ,EAAE;AACrC,QAAQ,KAAK,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE;AAC/C,YAAY;AACZ,gBAAgB,IAAI,KAAK,QAAQ;AACjC,gBAAgB,QAAQ;AACxB,gBAAgB,CAAC,QAAQ,CAAC,gBAAgB;AAC1C,gBAAgB,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;AACvC,cAAc;AACd,gBAAgB,OAAO,IAAI,CAAC;AAC5B,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,uBAAuB,CAAC,QAAQ,EAAE;AAC3C,IAAI,MAAM,EAAE,KAAK,EAAE,GAAGA,kBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACrD;AACA,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC;;ACpgBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB,CAAC;AACvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC;AAChB,QAAQ,UAAU,GAAG,IAAI;AACzB,QAAQ,KAAK,GAAG,IAAI;AACpB,QAAQ,QAAQ,GAAG,IAAI;AACvB,QAAQ,EAAE;AACV,QAAQ,YAAY;AACpB,QAAQ,YAAY;AACpB,KAAK,EAAE;AACP;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;AACrC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AAC3B;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;AACrB;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;AACzC;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;AACzC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,MAAM,GAAG,GAAG,IAAI,CAACC,wBAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AAChD;AACA;AACA,QAAQ,IAAI,GAAG,CAAC,KAAK,YAAY,KAAK,EAAE;AACxC,YAAY,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;AACrE,SAAS;AACT;AACA,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,CAACA,wBAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG;AAC5B,QAAQ,MAAM;AACd,YAAY,UAAU,EAAE,OAAO;AAC/B,YAAY,GAAG,GAAG;AAClB,SAAS,GAAG,IAAI,CAAC;AACjB;AACA,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;;AC7GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA,MAAM,EAAE,SAAS,EAAE,GAAGC,6BAAS,CAAC;AAChC;AACA,MAAM,aAAa,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,iBAAiB,CAAC,QAAQ,EAAE;AACrC,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;AACjC,QAAQ,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACxC,KAAK;AACL,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAClD,QAAQ,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC1B,KAAK;AACL,IAAI,OAAO,EAAE,CAAC;AACd,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,QAAQ,EAAE;AAC7B,IAAI,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;AAC/B,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL,IAAI,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,IAAI;AACnC,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACvC,YAAY,OAAO,IAAI,SAAS;AAChC,gBAAgB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAChC;AACA;AACA,gBAAgB,EAAE,GAAG,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE;AACtD,aAAa,CAAC;AACd,SAAS;AACT,QAAQ,OAAO,IAAI,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AACrD,KAAK,CAAC,CAAC;AACP,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;AAC/C,IAAI,OAAO;AACX,QAAQ,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AAC1D,QAAQ,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;AAC1D,KAAK,CAAC;AACN,CAAC;AACD;AACA;AACA;AACA;AACA,MAAM,cAAc,CAAC;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE;AAClD,QAAQ,MAAM,eAAe,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;AACzD,QAAQ,MAAM,eAAe,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;AACjE,QAAQ,IAAI,gBAAgB,GAAG,KAAK,CAAC;AACrC;AACA,QAAQ,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;AAC1C,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT;AACA;AACA,QAAQ,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE;AAC/C,YAAY,IAAIL,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACpE,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,uEAAuE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACrH,aAAa;AACb,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACvC,gBAAgB,gBAAgB,GAAG,IAAI,CAAC;AACxC,aAAa;AACb,SAAS;AACT,QAAQ,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE;AAC/C,YAAY,IAAIA,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACpE,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,uEAAuE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACrH,aAAa;AACb,SAAS;AACT;AACA,QAAQ,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;AACpD,QAAQ,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;AACpD;AACA,QAAQ,OAAO,IAAI,cAAc;AACjC,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACpC,YAAY,QAAQ;AACpB,YAAY,gBAAgB;AAC5B,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE;AACrB,QAAQ,IAAI,CAAC,CAAC,EAAE;AAChB,YAAY,OAAO,CAAC,IAAI,IAAI,cAAc;AAC1C,gBAAgB,CAAC,CAAC,QAAQ;AAC1B,gBAAgB,CAAC,CAAC,QAAQ;AAC1B,gBAAgB,CAAC,CAAC,gBAAgB;AAClC,aAAa,CAAC;AACd,SAAS;AACT,QAAQ,IAAI,CAAC,CAAC,EAAE;AAChB,YAAY,OAAO,IAAI,cAAc;AACrC,gBAAgB,CAAC,CAAC,QAAQ;AAC1B,gBAAgB,CAAC,CAAC,QAAQ;AAC1B,gBAAgB,CAAC,CAAC,gBAAgB;AAClC,aAAa,CAAC;AACd,SAAS;AACT;AACA,QAAQE,0BAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AACnD,QAAQ,OAAO,IAAI,cAAc;AACjC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACzC,YAAY,CAAC,CAAC,QAAQ;AACtB,YAAY,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,gBAAgB;AACpD,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,GAAG,KAAK,EAAE;AAC9D;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC;AACA;AACA,QAAQ,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;AACjD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,CAAC,QAAQ,EAAE;AACnB,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAACF,wBAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AACxE,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,+CAA+C,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F,SAAS;AACT,QAAQ,MAAM,YAAY,GAAGA,wBAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACpE;AACA,QAAQ,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAC1D,YAAY,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACnE,aAAa,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;AACrE,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;AACxC,YAAY,OAAO;AACnB,gBAAgB,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClD,gBAAgB,QAAQ,EAAE,IAAI,CAAC,QAAQ;AACvC,aAAa,CAAC;AACd,SAAS;AACT,QAAQ,OAAO;AACf,YAAY,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;AACjD,YAAY,QAAQ,EAAE,IAAI,CAAC,QAAQ;AACnC,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,CAACI,wBAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG;AAC5B,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;AAC7B,KAAK;AACL;;AC9NA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC;AACtD,IAAI,aAAa,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK;AACxE,QAAQ,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AAC3B,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK,EAAE,EAAE,CAAC;AACV,IAAI,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,UAAU,EAAE;AACrC,IAAI,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;AACjF;AACA,IAAI,IAAI,aAAa,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,EAAE;AAC3E,QAAQ,OAAO,aAAa,CAAC;AAC7B,KAAK;AACL;AACA,IAAI,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE;AAC3C,QAAQ,OAAO,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;AAC/D,KAAK;AACL;AACA,IAAI,OAAO,CAAC,CAAC;AACb,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,MAAM,EAAE;AACpC;AACA,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE;AACtB,QAAQ,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI;AACpD,YAAY,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACpD;AACA,YAAY,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;AAChD,gBAAgB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,qBAAqB,CAAC,UAAU,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAC;AACrG,aAAa,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;AACvF,gBAAgB,UAAU,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAC;AACjG,aAAa;AACb,SAAS,CAAC,CAAC;AACX,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,UAAU,EAAE;AACrC,IAAI,OAAO,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,UAAU,EAAE;AACrC,IAAI,IAAI,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC;AAC1E;AACA,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;AACtC,QAAQ,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;AAC1C,KAAK;AACL,IAAI,OAAO,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACrD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,MAAM,EAAE;AACtC,IAAI,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,CAAC,eAAe,EAAE;AAChD,IAAI,QAAQ,eAAe;AAC3B,QAAQ,KAAK,KAAK;AAClB,YAAY,OAAO,KAAK,CAAC;AACzB;AACA,QAAQ,KAAK,IAAI,CAAC;AAClB,QAAQ,KAAK,MAAM,CAAC;AACpB,QAAQ,KAAK,WAAW,CAAC;AACzB,QAAQ,KAAK,UAAU;AACvB,YAAY,OAAO,UAAU,CAAC;AAC9B;AACA,QAAQ,KAAK,IAAI,CAAC;AAClB,QAAQ,KAAK,KAAK,CAAC;AACnB,QAAQ,KAAK,OAAO,CAAC;AACrB,QAAQ,KAAK,UAAU,CAAC;AACxB,QAAQ,KAAK,UAAU;AACvB,YAAY,OAAO,UAAU,CAAC;AAC9B;AACA,QAAQ;AACR,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,kFAAkF,CAAC,CAAC,CAAC;AACrI,KAAK;AACL;;;;;;;;;;;;AC7HA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,0BAA0B,GAAG;AACnC,IAAI,0BAA0B;AAC9B,QAAQ,0EAA0E;AAClF,IAAI,2BAA2B;AAC/B,QAAQ,qDAAqD;AAC7D,QAAQ,gEAAgE;AACxE,IAAI,+BAA+B;AACnC,QAAQ,qDAAqD;AAC7D,QAAQ,kEAAkE;AAC1E,QAAQ,kEAAkE;AAC1E,CAAC,CAAC;AACF;AACA,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE;AACnD,IAAI,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC3D;AACA,IAAI,IAAI,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AAC5C,QAAQ,OAAO;AACf,KAAK;AACL,IAAI,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvC;AACA,IAAI,MAAM,GAAG,GAAGJ,wBAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;AACrD,IAAI,MAAM,OAAO,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;AAC1D;AACA,IAAI,OAAO,CAAC,WAAW;AACvB,QAAQ,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;AACxC,QAAQ,oBAAoB;AAC5B,QAAQ,SAAS;AACjB,KAAK,CAAC;AACN;;ACtDA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,UAAU,GAAG;AACnB,IAAI,EAAE,EAAE,yCAAyC;AACjD,IAAI,OAAO,EAAE,yCAAyC;AACtD,IAAI,WAAW,EAAE,yBAAyB;AAC1C,IAAI,WAAW,EAAE;AACjB,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,OAAO;AACzB,YAAY,QAAQ,EAAE,CAAC;AACvB,YAAY,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAChC,SAAS;AACT,QAAQ,eAAe,EAAE;AACzB,YAAY,IAAI,EAAE,SAAS;AAC3B,YAAY,OAAO,EAAE,CAAC;AACtB,SAAS;AACT,QAAQ,uBAAuB,EAAE;AACjC,YAAY,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAC9E,SAAS;AACT,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;AACvF,SAAS;AACT,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,OAAO;AACzB,YAAY,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AACrC,YAAY,QAAQ,EAAE,CAAC;AACvB,YAAY,WAAW,EAAE,IAAI;AAC7B,SAAS;AACT,KAAK;AACL,IAAI,IAAI,EAAE,QAAQ;AAClB,IAAI,UAAU,EAAE;AAChB,QAAQ,EAAE,EAAE;AACZ,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,OAAO,EAAE;AACjB,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,KAAK,EAAE;AACf,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,OAAO,EAAE,GAAG;AACpB,QAAQ,UAAU,EAAE;AACpB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,OAAO,EAAE,CAAC;AACtB,YAAY,gBAAgB,EAAE,IAAI;AAClC,SAAS;AACT,QAAQ,OAAO,EAAE;AACjB,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,gBAAgB,EAAE;AAC1B,YAAY,IAAI,EAAE,SAAS;AAC3B,YAAY,OAAO,EAAE,KAAK;AAC1B,SAAS;AACT,QAAQ,OAAO,EAAE;AACjB,YAAY,IAAI,EAAE,QAAQ;AAC1B,SAAS;AACT,QAAQ,gBAAgB,EAAE;AAC1B,YAAY,IAAI,EAAE,SAAS;AAC3B,YAAY,OAAO,EAAE,KAAK;AAC1B,SAAS;AACT,QAAQ,SAAS,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AAC5D,QAAQ,SAAS,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE;AACpE,QAAQ,OAAO,EAAE;AACjB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,MAAM,EAAE,OAAO;AAC3B,SAAS;AACT,QAAQ,eAAe,EAAE;AACzB,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE;AACnC,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE;AAC7B,aAAa;AACb,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,KAAK,EAAE;AACf,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE;AAC7B,gBAAgB,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACrD,aAAa;AACb,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,QAAQ,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AAC3D,QAAQ,QAAQ,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE;AACnE,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,SAAS;AAC3B,YAAY,OAAO,EAAE,KAAK;AAC1B,SAAS;AACT,QAAQ,aAAa,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AAChE,QAAQ,aAAa,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE;AACxE,QAAQ,QAAQ,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACvD,QAAQ,oBAAoB,EAAE;AAC9B,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE;AACnC,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE;AAC7B,aAAa;AACb,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,WAAW,EAAE;AACrB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAC/C,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,UAAU,EAAE;AACpB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAC/C,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,iBAAiB,EAAE;AAC3B,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAC/C,YAAY,OAAO,EAAE,GAAG;AACxB,SAAS;AACT,QAAQ,YAAY,EAAE;AACtB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,oBAAoB,EAAE;AAClC,gBAAgB,KAAK,EAAE;AACvB,oBAAoB,EAAE,IAAI,EAAE,GAAG,EAAE;AACjC,oBAAoB,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACzD,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,EAAE;AACd,YAAY,IAAI,EAAE,OAAO;AACzB,YAAY,QAAQ,EAAE,CAAC;AACvB,YAAY,WAAW,EAAE,IAAI;AAC7B,SAAS;AACT,QAAQ,IAAI,EAAE;AACd,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACrD,gBAAgB;AAChB,oBAAoB,IAAI,EAAE,OAAO;AACjC,oBAAoB,KAAK,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;AAChE,oBAAoB,QAAQ,EAAE,CAAC;AAC/B,oBAAoB,WAAW,EAAE,IAAI;AACrC,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAClC,QAAQ,KAAK,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACpD,QAAQ,KAAK,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACpD,QAAQ,KAAK,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;AACpD,QAAQ,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE;AAC1B,KAAK;AACL,IAAI,YAAY,EAAE;AAClB,QAAQ,gBAAgB,EAAE,CAAC,SAAS,CAAC;AACrC,QAAQ,gBAAgB,EAAE,CAAC,SAAS,CAAC;AACrC,KAAK;AACL,IAAI,OAAO,EAAE,GAAG;AAChB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,cAAe,CAAC,iBAAiB,GAAG,EAAE,KAAK;AAC3C,IAAI,MAAM,GAAG,GAAG,IAAIM,uBAAG,CAAC;AACxB,QAAQ,IAAI,EAAE,KAAK;AACnB,QAAQ,WAAW,EAAE,IAAI;AACzB,QAAQ,cAAc,EAAE,KAAK;AAC7B,QAAQ,WAAW,EAAE,QAAQ;AAC7B,QAAQ,OAAO,EAAE,IAAI;AACrB,QAAQ,QAAQ,EAAE,MAAM;AACxB,QAAQ,GAAG,iBAAiB;AAC5B,KAAK,CAAC,CAAC;AACP;AACA,IAAI,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;AAClC;AACA,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC,EAAE,CAAC;AAC1C;AACA,IAAI,OAAO,GAAG,CAAC;AACf,CAAC;;AC9LD;AACA;AACA;AACA;AACA;AACA,MAAM,oBAAoB,GAAG;AAC7B,IAAI,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC/B,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC3B,IAAI,OAAO,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AACtD,IAAI,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC/B,IAAI,SAAS,EAAE;AACf,QAAQ,IAAI,EAAE,OAAO;AACrB,QAAQ,KAAK,EAAE,EAAE,IAAI,EAAE,8BAA8B,EAAE;AACvD,QAAQ,eAAe,EAAE,KAAK;AAC9B,KAAK;AACL,IAAI,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;AACxC,IAAI,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AACrC,IAAI,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;AAC9B,IAAI,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AACjC,IAAI,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC7B,IAAI,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAChC,IAAI,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;AACvC,IAAI,6BAA6B,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;AACtD;AACA,IAAI,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AACpC,CAAC,CAAC;AACF;AACA,MAAM,YAAY,GAAG;AACrB,IAAI,WAAW,EAAE;AACjB,QAAQ,eAAe,EAAE;AACzB,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE;AAClC,gBAAgB;AAChB,oBAAoB,IAAI,EAAE,OAAO;AACjC,oBAAoB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC7C,oBAAoB,eAAe,EAAE,KAAK;AAC1C,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,uBAAuB,EAAE;AACjC,YAAY,KAAK,EAAE;AACnB,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE;AAClC,gBAAgB;AAChB,oBAAoB,IAAI,EAAE,OAAO;AACjC,oBAAoB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;AAC7C,oBAAoB,eAAe,EAAE,KAAK;AAC1C,oBAAoB,QAAQ,EAAE,CAAC;AAC/B,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA;AACA,QAAQ,YAAY,EAAE;AACtB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,UAAU,EAAE;AACxB,gBAAgB,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;AACzC,gBAAgB,cAAc,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AACzE,gBAAgB,GAAG,oBAAoB;AACvC,aAAa;AACb,YAAY,oBAAoB,EAAE,KAAK;AACvC,SAAS;AACT;AACA;AACA,QAAQ,cAAc,EAAE;AACxB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,UAAU,EAAE;AACxB,gBAAgB,aAAa,EAAE,EAAE,IAAI,EAAE,+BAA+B,EAAE;AACxE,gBAAgB,KAAK,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE;AACxE,gBAAgB,GAAG,oBAAoB;AACvC,aAAa;AACb,YAAY,QAAQ,EAAE,CAAC,OAAO,CAAC;AAC/B,YAAY,oBAAoB,EAAE,KAAK;AACvC,SAAS;AACT,KAAK;AACL;AACA,IAAI,IAAI,EAAE,4BAA4B;AACtC,CAAC;;AC5ED;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;AAChC,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;AACpB;AACA,IAAI,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACxD,QAAQ,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;AACpD,YAAY,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAC9B,SAAS;AACT,KAAK;AACL;AACA,IAAI,OAAO,IAAI,CAAC;AAChB,CAAC;AACD;AACA,MAAM,cAAc,GAAG,OAAO,CAACC,2BAAO,CAAC,MAAM,EAAEA,2BAAO,CAAC,GAAG,CAAC,CAAC;AAC5D,MAAM,cAAc,GAAG;AACvB,IAAI,OAAO,EAAE,KAAK;AAClB,IAAI,iBAAiB,EAAE,KAAK;AAC5B,CAAC,CAAC;AACF,MAAM,cAAc,GAAG;AACvB,IAAI,MAAM,EAAE,KAAK;AACjB,IAAI,aAAa,EAAE,KAAK;AACxB,IAAI,cAAc,EAAE,KAAK;AACzB,IAAI,UAAU,EAAE,KAAK;AACrB,CAAC,CAAC;AACF;AACA,MAAM,cAAc,GAAG;AACvB,IAAI,cAAc,EAAE,KAAK;AACzB,IAAI,oBAAoB,EAAE,KAAK;AAC/B,IAAI,OAAO,EAAE,KAAK;AAClB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA,mBAAe,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACtC;AACA;AACA,IAAI,OAAO,EAAE;AACb,QAAQ,OAAO,EAAEA,2BAAO,CAAC,GAAG;AAC5B,KAAK;AACL,IAAI,GAAG,EAAE;AACT,QAAQ,OAAO,EAAE,cAAc;AAC/B,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,CAAC;AAC1B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,cAAc;AAC/B,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,CAAC;AAC1B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,cAAc;AAC/B,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,CAAC;AAC1B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AACzD,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,CAAC;AAC1B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AACzD,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,CAAC;AAC1B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AACzD,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,EAAE;AAC3B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AAC5E,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,EAAE;AAC3B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AAC/F,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,EAAE;AAC3B,SAAS;AACT,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAE,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE;AAC/F,QAAQ,aAAa,EAAE;AACvB,YAAY,WAAW,EAAE,EAAE;AAC3B,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,OAAO,EAAE;AACb,QAAQ,OAAO,EAAEA,2BAAO,CAAC,OAAO;AAChC,KAAK;AACL,IAAI,IAAI,EAAE;AACV,QAAQ,OAAO,EAAEA,2BAAO,CAAC,IAAI;AAC7B,QAAQ,aAAa,EAAE;AACvB,YAAY,YAAY,EAAE;AAC1B,gBAAgB,YAAY,EAAE,IAAI;AAClC,aAAa;AACb,SAAS;AACT,KAAK;AACL,IAAI,qBAAqB,EAAE;AAC3B,QAAQ,OAAO,EAAEA,2BAAO,CAAC,qBAAqB,CAAC;AAC/C,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAEA,2BAAO,CAAC,MAAM;AAC/B,KAAK;AACL,IAAI,aAAa,EAAE;AACnB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,aAAa;AACtC,KAAK;AACL;AACA;AACA,IAAI,QAAQ,EAAE;AACd,QAAQ,OAAO,EAAEA,2BAAO,CAAC,QAAQ;AACjC,QAAQ,aAAa,EAAE;AACvB,YAAY,YAAY,EAAE;AAC1B,gBAAgB,YAAY,EAAE,IAAI;AAClC,aAAa;AACb,SAAS;AACT,KAAK;AACL,IAAI,GAAG,EAAE;AACT,QAAQ,OAAO,EAAEA,2BAAO,CAAC,GAAG;AAC5B,KAAK;AACL,IAAI,KAAK,EAAE;AACX,QAAQ,OAAO,EAAEA,2BAAO,CAAC,KAAK;AAC9B,KAAK;AACL,IAAI,OAAO,EAAE;AACb,QAAQ,OAAO,EAAEA,2BAAO,CAAC,OAAO;AAChC,KAAK;AACL,IAAI,IAAI,EAAE;AACV,QAAQ,OAAO,EAAEA,2BAAO,CAAC,IAAI;AAC7B,KAAK;AACL,IAAI,SAAS,EAAE;AACf,QAAQ,OAAO,EAAEA,2BAAO,CAAC,SAAS;AAClC,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAEA,2BAAO,CAAC,MAAM;AAC/B,KAAK;AACL,IAAI,KAAK,EAAE;AACX,QAAQ,OAAO,EAAEA,2BAAO,CAAC,KAAK;AAC9B,KAAK;AACL,IAAI,WAAW,EAAE;AACjB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,WAAW;AACpC,KAAK;AACL,IAAI,OAAO,EAAE;AACb,QAAQ,OAAO,EAAEA,2BAAO,CAAC,OAAO;AAChC,KAAK;AACL,IAAI,MAAM,EAAE;AACZ,QAAQ,OAAO,EAAEA,2BAAO,CAAC,MAAM;AAC/B,KAAK;AACL,IAAI,KAAK,EAAE;AACX,QAAQ,OAAO,EAAEA,2BAAO,CAAC,KAAK;AAC9B,KAAK;AACL,IAAI,UAAU,EAAE;AAChB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,UAAU;AACnC,KAAK;AACL,IAAI,WAAW,EAAE;AACjB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,WAAW;AACpC,KAAK;AACL,IAAI,OAAO,EAAE;AACb,QAAQ,OAAO,EAAEA,2BAAO,CAAC,OAAO;AAChC,KAAK;AACL,IAAI,QAAQ,EAAE;AACd,QAAQ,OAAO,EAAEA,2BAAO,CAAC,QAAQ;AACjC,KAAK;AACL,IAAI,SAAS,EAAE;AACf,QAAQ,OAAO,EAAEA,2BAAO,CAAC,SAAS;AAClC,KAAK;AACL,IAAI,aAAa,EAAE;AACnB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,aAAa;AACtC,KAAK;AACL,IAAI,YAAY,EAAE;AAClB,QAAQ,OAAO,EAAEA,2BAAO,CAAC,YAAY;AACrC,KAAK;AACL,CAAC,CAAC,CAAC;;AC1MH;AACA;AACA;AACA;AAcA;AACA,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB;AACA,MAAM,cAAc,GAAG,IAAI,OAAO,EAAE,CAAC;AACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC;AAChC;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC;AACnB,MAAM,WAAW,GAAG;AACpB,IAAI,KAAK,EAAE,CAAC;AACZ,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,GAAG,EAAE,CAAC;AACV,CAAC,CAAC;AACF;AACA,MAAM,SAAS,GAAG,IAAI,OAAO,EAAE,CAAC;AAChC;AACA;AACA;AACA;AACA;AACe,MAAM,eAAe,CAAC;AACrC,IAAI,WAAW,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE;AACnD,QAAQ,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;AACzC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,CAAC,IAAI,EAAE;AAC/B,QAAQ,IAAI,CAAC,IAAI,EAAE;AACnB,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT;AACA,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;AACpE;AACA;AACA,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AACnC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE;AAC/B,gBAAgB,OAAO;AACvB,oBAAoB,IAAI,EAAE,OAAO;AACjC,oBAAoB,KAAK,EAAE,MAAM;AACjC,oBAAoB,QAAQ,EAAE,CAAC;AAC/B,oBAAoB,QAAQ,EAAE,MAAM,CAAC,MAAM;AAC3C,iBAAiB,CAAC;AAClB,aAAa;AACb,YAAY,OAAO;AACnB,gBAAgB,IAAI,EAAE,OAAO;AAC7B,gBAAgB,QAAQ,EAAE,CAAC;AAC3B,gBAAgB,QAAQ,EAAE,CAAC;AAC3B,aAAa,CAAC;AACd;AACA,SAAS;AACT;AACA;AACA,QAAQ,OAAO,MAAM,IAAI,IAAI,CAAC;AAC9B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,CAAC,OAAO,EAAE;AAClC,QAAQ,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AACvE,QAAQ,MAAM,YAAY,GAAG,OAAO,QAAQ,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC;AAC3G;AACA,QAAQ,IAAI,YAAY,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,EAAE;AAC5E,YAAY,OAAO,YAAY,CAAC;AAChC,SAAS;AACT;AACA,QAAQ,MAAM,IAAI,KAAK,CAAC,CAAC,qFAAqF,EAAEH,wBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AACxL;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE;AAC3C,QAAQ,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AACvC,YAAY,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAC3D;AACA,YAAY,IAAI,MAAM,EAAE;AACxB,gBAAgB,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,aAAa;AACb,SAAS;AACT;AACA,QAAQ,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtD;AACA,QAAQ,IAAI,YAAY,EAAE;AAC1B,YAAY,YAAY,CAAC,YAAY,CAAC,CAAC;AACvC,YAAY,IAAI,YAAY,CAAC,MAAM,EAAE;AACrC,gBAAgB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG;AACvD,oBAAoB,KAAK,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;AACxF,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE;AAC9D,QAAQ,IAAI;AACZ,YAAY,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAChE;AACA,YAAY,IAAI,QAAQ,KAAK,CAAC,EAAE;AAChC,gBAAgB,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AAC9F,aAAa;AACb,SAAS,CAAC,OAAO,GAAG,EAAE;AACtB,YAAY,MAAM,eAAe,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACrG;AACA,YAAY,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5C,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;AACpE,aAAa,MAAM;AACnB,gBAAgB,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;AACjD,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAmB;AACvB,QAAQ,WAAW;AACnB,QAAQ,MAAM;AACd,QAAQ,gBAAgB,GAAG,IAAI;AAC/B,MAAM;AACN;AACA;AACA,QAAQ,IAAI,CAAC,WAAW,EAAE;AAC1B,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI;AAC/C,YAAY,MAAM,GAAG,GAAG,gBAAgB,CAAC,EAAE,CAAC,IAAII,YAAmB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AACpF;AACA,YAAY,IAAI,CAAC,GAAG,EAAE;AACtB,gBAAgB,MAAM,OAAO,GAAG,CAAC,EAAE,MAAM,CAAC,sBAAsB,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC;AACrF;AACA,gBAAgB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AACzC,aAAa;AACb,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa;AACjB,QAAQ,WAAW;AACnB,QAAQ,MAAM;AACd,QAAQ,iBAAiB,GAAG,IAAI;AAChC,MAAM;AACN,QAAQ,IAAI,CAAC,WAAW,EAAE;AAC1B,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI;AAC/C,YAAY,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AACpF;AACA,YAAY,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;AACxE,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE;AAClD,QAAQ,IAAI,CAAC,aAAa,EAAE;AAC5B,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;AACrC,aAAa,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,KAAK;AAC9D,gBAAgB,IAAI;AACpB,oBAAoBC,qBAA+B,CAAC,eAAe,CAAC,CAAC;AACrE,iBAAiB,CAAC,OAAO,GAAG,EAAE;AAC9B,oBAAoB,MAAM,IAAI,KAAK,CAAC,CAAC,gCAAgC,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACrI,iBAAiB;AACjB,aAAa,CAAC,CAAC;AACf,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,iBAAiB,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE;AAC3D,QAAQ,IAAI,aAAa,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,EAAE;AAC3D,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,sCAAsC,EAAE,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC9H,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,MAAM,EAAE;AACzB,QAAQ,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI;AACnC,YAAY,IAAI,KAAK,CAAC,OAAO,KAAK,sBAAsB,EAAE;AAC1D,gBAAgB,MAAM,qBAAqB,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC;AACxK;AACA,gBAAgB,OAAO,CAAC,+BAA+B,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAClF,aAAa;AACb,YAAY,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,EAAE;AAC1C,gBAAgB,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/D,gBAAgB,MAAM,qBAAqB,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;AAClH,gBAAgB,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAClE;AACA,gBAAgB,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,8BAA8B,EAAE,qBAAqB,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;AAC1I,aAAa;AACb;AACA,YAAY,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;AAC/F;AACA,YAAY,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvF,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE;AAChD,QAAQ,cAAc,GAAG,cAAc,IAAI,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AACrE;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE;AACrC,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,wBAAwB,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1H,SAAS;AACT;AACA,QAAQ,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE;AAChE,YAAY,sBAAsB,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;AACzE,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,gBAAgB,EAAE;AAClE,QAAQ,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClD,QAAQ,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;AACpE,QAAQ,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AACvE,QAAQ,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACrD;AACA,QAAQ,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE;AACvD,YAAY,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAC1E,YAAY,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAC7E,YAAY,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACzD,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAmB,CAAC,WAAW,EAAE;AACrC,QAAQ,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;AACpF,QAAQ,MAAM,kBAAkB,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;AACxF,QAAQ,MAAM,aAAa,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AAC9E;AACA;AACA,QAAQ,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE;AAC3C,YAAY,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AACxC,gBAAgB,SAAS;AACzB,aAAa;AACb,YAAY,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnC;AACA,YAAY,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AAC9E,YAAY,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAChE,YAAY,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;AACxF,YAAY,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AAC3E,SAAS;AACT,KAAK;AACL;AACA;;ACpUA;AACA;AACA;AACA;AACA,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE;AAC5C,IAAI,IAAI,cAAc,GAAG,IAAI,CAAC;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACvC,QAAQ,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC7D,KAAK;AACL;AACA,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;AAC1C;AACA;AACA;AACA;AACA;AACA,QAAQ,MAAM,0BAA0B,GAAG,IAAI,MAAM,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;AAC5F,YAAY,sBAAsB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;AACxE;AACA,QAAQ,IAAI,0BAA0B,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE;AAC7D,YAAY,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,0BAA0B,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAChG,SAAS,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/E;AACA;AACA;AACA;AACA;AACA,YAAY,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7F,SAAS;AACT,KAAK,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACzD,QAAQ,cAAc,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;AACvD,KAAK;AACL;AACA,IAAI,OAAO,cAAc,CAAC;AAC1B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE;AAC5C,IAAI,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;AAC7B,QAAQ,IAAI,WAAW,GAAG,IAAI,MAAM,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACjF;AACA,QAAQ,IAAI,WAAW,EAAE;AACzB,YAAY,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;AAClC,SAAS;AACT;AACA,QAAQ,WAAW,GAAG,IAAI,MAAM,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAClF,QAAQ,IAAI,WAAW,EAAE;AACzB,YAAY,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,SAAS;AACT,KAAK,MAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AAClD,QAAQ,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjD,KAAK;AACL;AACA,IAAI,OAAO,QAAQ,CAAC;AACpB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,IAAI,EAAE;AACpC,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC9C;AACA,IAAI,OAAO,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACjC;;;;;;;;;ACrFA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,GAAGC,0BAAM,CAAC,aAAa,CAAC;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE;AAC7C,IAAI,IAAI;AACR,QAAQ,OAAO,aAAa,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AACjE,KAAK,CAAC,OAAO,KAAK,EAAE;AACpB;AACA;AACA,QAAQ;AACR,YAAY,OAAO,KAAK,KAAK,QAAQ;AACrC,YAAY,KAAK,KAAK,IAAI;AAC1B,YAAY,KAAK,CAAC,IAAI,KAAK,kBAAkB;AAC7C,YAAY,CAAC,KAAK,CAAC,YAAY;AAC/B,YAAY,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;AAC9C,UAAU;AACV,YAAY,KAAK,CAAC,OAAO,IAAI,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC,CAAC;AACrE,SAAS;AACT,QAAQ,MAAM,KAAK,CAAC;AACpB,KAAK;AACL;;;;;;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAsBA;AACA,MAAMC,SAAO,GAAGC,oBAAa,CAAC,mDAAe,CAAC,CAAC;AAC/C;AACA,MAAMd,OAAK,GAAGC,6BAAS,CAAC,+BAA+B,CAAC,CAAC;AACzD;AACA;AACA;AACA;AACA;AACA,MAAM,eAAe,GAAG;AACxB,IAAI,cAAc;AAClB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,eAAe;AACnB,IAAI,gBAAgB;AACpB,IAAI,WAAW;AACf,IAAI,cAAc;AAClB,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMI,kBAAgB,GAAG,IAAI,OAAO,EAAE,CAAC;AACvC;AACA;AACA,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAAE,CAAC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,UAAU,CAAC,UAAU,EAAE;AAChC,IAAI;AACJ,QAAQ,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC;AACzC,QAAQH,wBAAI,CAAC,UAAU,CAAC,UAAU,CAAC;AACnC,MAAM;AACN,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,QAAQ,CAAC,QAAQ,EAAE;AAC5B,IAAI,OAAOa,sBAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,QAAQ,EAAE;AACtC,IAAIf,OAAK,CAAC,CAAC,0BAA0B,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnD;AACA;AACA,IAAI,MAAM,IAAI,GAAGa,SAAO,CAAC,SAAS,CAAC,CAAC;AACpC;AACA,IAAI,IAAI;AACR;AACA;AACA,QAAQ,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;AACnD,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQb,OAAK,CAAC,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACtD,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,QAAQ,EAAE;AACtC,IAAIA,OAAK,CAAC,CAAC,0BAA0B,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnD;AACA,IAAI,IAAI;AACR,QAAQ,OAAO,IAAI,CAAC,KAAK,CAACgB,iCAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC7D,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQhB,OAAK,CAAC,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACtD,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,QAAQ,CAAC,CAAC,eAAe,GAAG,qBAAqB,CAAC;AAClD,QAAQ,CAAC,CAAC,WAAW,GAAG;AACxB,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,OAAO,EAAE,CAAC,CAAC,OAAO;AAC9B,SAAS,CAAC;AACV,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,QAAQ,EAAE;AACxC,IAAIA,OAAK,CAAC,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrD;AACA;AACA,IAAI,MAAM,IAAI,GAAGa,SAAO,CAAC,SAAS,CAAC,CAAC;AACpC;AACA,IAAI,IAAI;AACR,QAAQ,OAAO,IAAI,CAAC,IAAI,CAACG,iCAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,+BAA+B,EAAE,CAAC;AAC7F,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQhB,OAAK,CAAC,iCAAiC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;AAC9D,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,CAAC,QAAQ,EAAE;AACpC,IAAIA,OAAK,CAAC,CAAC,wBAAwB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACjD,IAAI,IAAI;AACR,QAAQ,OAAOiB,+BAAW,CAAC,QAAQ,CAAC,CAAC;AACrC,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQjB,OAAK,CAAC,CAAC,+BAA+B,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5D,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,yBAAyB,CAAC,QAAQ,EAAE;AAC7C,IAAIA,OAAK,CAAC,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC3D,IAAI,IAAI;AACR,QAAQ,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACzD;AACA,QAAQ,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE;AACtE,YAAY,MAAM,MAAM,CAAC,MAAM;AAC/B,gBAAgB,IAAI,KAAK,CAAC,sDAAsD,CAAC;AACjF,gBAAgB,EAAE,IAAI,EAAE,+BAA+B,EAAE;AACzD,aAAa,CAAC;AACd,SAAS;AACT;AACA,QAAQ,OAAO,WAAW,CAAC,YAAY,CAAC;AACxC,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQA,OAAK,CAAC,CAAC,iCAAiC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC9D,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAChF,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,QAAQ,EAAE;AACxC,IAAIA,OAAK,CAAC,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrD;AACA,IAAI,IAAI;AACR,QAAQ,OAAO,QAAQ,CAAC,QAAQ,CAAC;AACjC,aAAa,KAAK,CAAC,SAAS,CAAC;AAC7B,aAAa,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACzE,KAAK,CAAC,OAAO,CAAC,EAAE;AAChB,QAAQA,OAAK,CAAC,CAAC,kCAAkC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/D,QAAQ,CAAC,CAAC,OAAO,GAAG,CAAC,gCAAgC,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACvF,QAAQ,MAAM,CAAC,CAAC;AAChB,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE;AACvE,IAAI,OAAO,MAAM,CAAC,MAAM;AACxB,QAAQ,IAAI,KAAK,CAAC,CAAC,uBAAuB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAC1E,QAAQ;AACR,YAAY,eAAe;AAC3B,YAAY,WAAW,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE;AACrD,SAAS;AACT,KAAK,CAAC;AACN,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,cAAc,CAAC,QAAQ,EAAE;AAClC,IAAI,QAAQE,wBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;AAClC,QAAQ,KAAK,KAAK,CAAC;AACnB,QAAQ,KAAK,MAAM;AACnB,YAAY,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAC9C;AACA,QAAQ,KAAK,OAAO;AACpB,YAAY,IAAIA,wBAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,cAAc,EAAE;AAC5D,gBAAgB,OAAO,yBAAyB,CAAC,QAAQ,CAAC,CAAC;AAC3D,aAAa;AACb,YAAY,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAChD;AACA,QAAQ,KAAK,OAAO,CAAC;AACrB,QAAQ,KAAK,MAAM;AACnB,YAAY,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAChD;AACA,QAAQ;AACR,YAAY,OAAO,oBAAoB,CAAC,QAAQ,CAAC,CAAC;AAClD,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE;AAChE;AACA,IAAI,IAAIF,OAAK,CAAC,OAAO,EAAE;AACvB,QAAQ,IAAI,cAAc,GAAG,IAAI,CAAC;AAClC;AACA,QAAQ,IAAI;AACZ,YAAY,MAAM,eAAe,GAAGkB,OAAsB;AAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;AACzC,gBAAgB,UAAU;AAC1B,aAAa,CAAC;AACd,YAAY,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE,GAAGL,SAAO,CAAC,eAAe,CAAC,CAAC;AACrE;AACA,YAAY,cAAc,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACrD,SAAS,CAAC,OAAO,KAAK,EAAE;AACxB,YAAYb,OAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AAChE,YAAY,cAAc,GAAG,OAAO,CAAC;AACrC,SAAS;AACT;AACA,QAAQA,OAAK,CAAC,iBAAiB,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;AAC3D,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa;AACtB,IAAI,EAAE,GAAG,EAAE,wBAAwB,EAAE;AACrC,IAAI,YAAY;AAChB,IAAI,YAAY;AAChB,IAAI,gBAAgB;AACpB,IAAI,qBAAqB;AACzB,EAAE;AACF,IAAI,MAAM,QAAQ,GAAG,gBAAgB;AACrC,UAAUE,wBAAI,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC;AAC7C,UAAU,EAAE,CAAC;AACb,IAAI,MAAM,aAAa;AACvB,QAAQ,CAAC,qBAAqB,IAAIA,wBAAI,CAAC,OAAO,CAAC,GAAG,EAAE,qBAAqB,CAAC;AAC1E,SAAS,QAAQ,IAAIA,wBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5C,QAAQ,GAAG,CAAC;AACZ,IAAI,MAAM,IAAI;AACd,QAAQ,YAAY;AACpB,SAAS,QAAQ,IAAIA,wBAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAClD,QAAQ,EAAE,CAAC;AACX,IAAI,MAAM,cAAc;AACxB,QAAQ,wBAAwB;AAChC,SAAS,QAAQ,IAAIA,wBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5C,QAAQ,GAAG,CAAC;AACZ,IAAI,MAAM,IAAI,GAAG,YAAY,IAAI,QAAQ,CAAC;AAC1C;AACA,IAAI,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;AACnE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,CAAC,MAAM,EAAE;AACjC;AACA;AACA,IAAI,IAAI,gBAAgB,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACzD;AACA,IAAI,IAAI,gBAAgB,EAAE;AAC1B,QAAQ,OAAO,gBAAgB,CAAC;AAChC,KAAK;AACL;AACA,IAAI,gBAAgB,GAAG;AACvB,QAAQ,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;AACrC,QAAQ,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE;AAC/C,QAAQ,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE;AAC3C,QAAQ,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;AACjC,KAAK,CAAC;AACN;AACA;AACA,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AACpD;AACA,IAAI,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,kBAAkB,CAAC;AACzB;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC;AAChB,QAAQ,oBAAoB,GAAG,IAAI,GAAG,EAAE;AACxC,QAAQ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;AAC3B,QAAQ,wBAAwB;AAChC,QAAQ,YAAY;AACpB,QAAQ,QAAQ,GAAG,cAAc;AACjC,QAAQ,aAAa;AACrB,QAAQ,kBAAkB;AAC1B,QAAQ,qBAAqB;AAC7B,QAAQ,0BAA0B;AAClC,KAAK,GAAG,EAAE,EAAE;AACZ,QAAQG,kBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE;AACnC,YAAY,oBAAoB;AAChC,YAAY,GAAG;AACf,YAAY,wBAAwB;AACpC,gBAAgB,wBAAwB;AACxC,gBAAgBH,wBAAI,CAAC,OAAO,CAAC,GAAG,EAAE,wBAAwB,CAAC;AAC3D,YAAY,YAAY;AACxB,YAAY,QAAQ;AACpB,YAAY,aAAa;AACzB,YAAY,kBAAkB;AAC9B,YAAY,qBAAqB;AACjC,YAAY,0BAA0B;AACtC,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;AAC1D,QAAQ,IAAI,CAAC,UAAU,EAAE;AACzB,YAAY,OAAO,IAAI,WAAW,EAAE,CAAC;AACrC,SAAS;AACT;AACA,QAAQ,MAAM,KAAK,GAAGG,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD,QAAQ,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC7E,QAAQ,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACpE;AACA,QAAQ,OAAO,IAAI,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC;AAC5C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,QAAQ,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;AAChD,QAAQ,MAAM,KAAK,GAAGA,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD,QAAQ,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC7E;AACA,QAAQ,OAAO,IAAI,WAAW,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;AAC5D,QAAQ,MAAM,KAAK,GAAGA,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD;AACA,QAAQ,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE;AAChD,YAAY,MAAM,GAAG,GAAG,aAAa;AACrC,gBAAgB,KAAK;AACrB,gBAAgB,QAAQ;AACxB,gBAAgB,IAAI;AACpB,gBAAgBH,wBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC;AAClD,gBAAgB,QAAQ;AACxB,aAAa,CAAC;AACd;AACA,YAAY,IAAIa,sBAAE,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAIA,sBAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE;AACnF,gBAAgB,IAAI,UAAU,CAAC;AAC/B;AACA,gBAAgB,IAAI;AACpB,oBAAoB,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9D,iBAAiB,CAAC,OAAO,KAAK,EAAE;AAChC,oBAAoB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,+BAA+B,EAAE;AAClF,wBAAwB,MAAM,KAAK,CAAC;AACpC,qBAAqB;AACrB,iBAAiB;AACjB;AACA,gBAAgB,IAAI,UAAU,EAAE;AAChC,oBAAoBf,OAAK,CAAC,CAAC,mBAAmB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChE,oBAAoB,OAAO,IAAI,WAAW;AAC1C,wBAAwB,GAAG,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE,GAAG,CAAC;AACrE,qBAAqB,CAAC;AACtB,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA,QAAQA,OAAK,CAAC,CAAC,yBAAyB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;AAC3D,QAAQ,OAAO,IAAI,WAAW,EAAE,CAAC;AACjC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,8BAA8B,CAAC,aAAa,EAAE;AACzD,QAAQ,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE;AAChD,YAAY,MAAM,QAAQ,GAAGE,wBAAI,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AAChE;AACA,YAAY,IAAIa,sBAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AACzC,gBAAgB,IAAI,QAAQ,KAAK,cAAc,EAAE;AACjD,oBAAoB,IAAI;AACxB,wBAAwB,yBAAyB,CAAC,QAAQ,CAAC,CAAC;AAC5D,wBAAwB,OAAO,QAAQ,CAAC;AACxC,qBAAqB,CAAC,MAAM,gBAAgB;AAC5C,iBAAiB,MAAM;AACvB,oBAAoB,OAAO,QAAQ,CAAC;AACpC,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC/B,QAAQ,MAAM,KAAK,GAAGV,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD,QAAQ,MAAM,GAAG,GAAG,aAAa;AACjC,YAAY,KAAK;AACjB,YAAY,QAAQ;AACpB,YAAY,KAAK,CAAC;AAClB,YAAY,QAAQ;AACpB,YAAY,KAAK,CAAC,GAAG;AACrB,SAAS,CAAC;AACV,QAAQ,MAAM,cAAc,GAAG,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClE;AACA,QAAQ,OAAO,IAAI,WAAW;AAC9B,YAAY,GAAG,IAAI,CAAC,0BAA0B,CAAC,cAAc,EAAE,GAAG,CAAC;AACnE,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,uBAAuB,GAAG;AAC9B,QAAQ,MAAM,KAAK,GAAGA,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD,QAAQ,MAAM,gBAAgB,GAAGH,wBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;AAC1E,QAAQ,MAAM,eAAe,GAAGA,wBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AACxE;AACA,QAAQ,IAAIa,sBAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE;AAC7C,YAAY,OAAO,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;AAC3D,SAAS;AACT,QAAQ,IAAIA,sBAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;AAC5C,YAAY,MAAM,IAAI,GAAG,kBAAkB,CAAC,eAAe,CAAC,CAAC;AAC7D;AACA,YAAY,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE;AAClE,gBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;AACvD,oBAAoB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;AACrG,iBAAiB;AACjB,gBAAgB,MAAM,GAAG,GAAG,aAAa;AACzC,oBAAoB,KAAK;AACzB,oBAAoB,QAAQ;AAC5B,oBAAoB,8BAA8B;AAClD,oBAAoB,eAAe;AACnC,oBAAoB,KAAK,CAAC,GAAG;AAC7B,iBAAiB,CAAC;AAClB;AACA,gBAAgB,OAAO,IAAI,WAAW;AACtC,oBAAoB,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC;AAC9E,iBAAiB,CAAC;AAClB,aAAa;AACb,SAAS;AACT;AACA,QAAQ,OAAO,IAAI,WAAW,EAAE,CAAC;AACjC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,GAAG,EAAE;AACzB,QAAQ,OAAO,IAAI,CAAC,oBAAoB,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5E,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,0BAA0B,CAAC,cAAc,EAAE,GAAG,EAAE;AACrD,QAAQ,MAAM,QAAQ,GAAG,IAAI,CAAC,0BAA0B;AACxD,YAAY,EAAE,cAAc,EAAE;AAC9B,YAAY,GAAG;AACf,SAAS,CAAC;AACV;AACA;AACA,QAAQ,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AACxC,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE;AACvC,gBAAgB,OAAO,CAAC,aAAa,CAAC,KAAK,GAAG,IAAI,CAAC;AACnD,aAAa;AACb,YAAY,MAAM,OAAO,CAAC;AAC1B,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,CAAC,UAAU,EAAE,GAAG,EAAE;AAC1C,QAAQ,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;AAChD;AACA,QAAQ,SAAS,CAAC,oBAAoB,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC7E,QAAQ,OAAO,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAChE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,GAAG,EAAE;AACjD,QAAQ,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,UAAU,EAAE,GAAG,UAAU,CAAC;AACnE,QAAQ,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM;AAC9C,YAAY,KAAK;AACjB,YAAY,aAAa;AACzB,YAAY,GAAG,CAAC,aAAa;AAC7B,SAAS,CAAC;AACV,QAAQ,MAAM,QAAQ,GAAG,IAAI,CAAC,8BAA8B,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC9E;AACA;AACA,QAAQ,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;AACxC;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,OAAO,CAAC,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9E;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,OAAO,CAAC,QAAQ,EAAE;AAClC,gBAAgB,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;AACtC,aAAa;AACb;AACA,YAAY,MAAM,OAAO,CAAC;AAC1B,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,8BAA8B;AACnC,QAAQ;AACR,YAAY,GAAG;AACf,YAAY,OAAO,EAAE,MAAM;AAC3B,YAAY,OAAO;AACnB,YAAY,cAAc;AAC1B,YAAY,cAAc;AAC1B,YAAY,MAAM,EAAE,UAAU;AAC9B,YAAY,aAAa;AACzB,YAAY,OAAO,EAAE,UAAU;AAC/B,YAAY,SAAS;AACrB,YAAY,6BAA6B;AACzC,YAAY,IAAI;AAChB,YAAY,KAAK;AACjB,YAAY,QAAQ;AACpB,YAAY,SAAS,EAAE,YAAY,GAAG,EAAE;AACxC,SAAS;AACT,QAAQ,GAAG;AACX,MAAM;AACN,QAAQ,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;AACrE,QAAQ,MAAM,aAAa,GAAG,cAAc,IAAI,IAAI,aAAa;AACjE,YAAY,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,GAAG,CAAC,cAAc,CAAC;AAC7E,YAAY,GAAG,CAAC,aAAa;AAC7B,SAAS,CAAC;AACV;AACA;AACA,QAAQ,KAAK,MAAM,UAAU,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;AAC7D,YAAY,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACtD,SAAS;AACT;AACA;AACA,QAAQ,MAAM,MAAM,GAAG,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACvE,QAAQ,MAAM,OAAO,GAAG,UAAU,IAAI,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACzE;AACA;AACA,QAAQ,IAAI,OAAO,EAAE;AACrB,YAAY,OAAO,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACnE,SAAS;AACT;AACA;AACA,QAAQ,MAAM;AACd;AACA;AACA,YAAY,IAAI,EAAE,GAAG,CAAC,IAAI;AAC1B,YAAY,IAAI,EAAE,GAAG,CAAC,IAAI;AAC1B,YAAY,QAAQ,EAAE,GAAG,CAAC,QAAQ;AAClC;AACA;AACA,YAAY,QAAQ,EAAE,IAAI;AAC1B,YAAY,GAAG;AACf,YAAY,OAAO;AACnB,YAAY,aAAa;AACzB,YAAY,cAAc;AAC1B,YAAY,MAAM;AAClB,YAAY,aAAa;AACzB,YAAY,OAAO;AACnB,YAAY,SAAS;AACrB,YAAY,6BAA6B;AACzC,YAAY,IAAI;AAChB,YAAY,KAAK;AACjB,YAAY,QAAQ;AACpB,SAAS,CAAC;AACV;AACA;AACA,QAAQ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE;AACtD,YAAY,OAAO,IAAI,CAAC,0BAA0B;AAClD,gBAAgB,YAAY,CAAC,CAAC,CAAC;AAC/B,gBAAgB,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/D,aAAa,CAAC;AACd,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,UAAU,EAAE,GAAG,EAAE;AAClC,QAAQf,OAAK,CAAC,qCAAqC,EAAE,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/E,QAAQ,IAAI;AACZ,YAAY,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;AAClD,gBAAgB,OAAO,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACxE,aAAa;AACb,YAAY,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;AAClD,gBAAgB,OAAO,IAAI,CAAC,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACvE,aAAa;AACb,YAAY,OAAO,IAAI,CAAC,4BAA4B,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACtE,SAAS,CAAC,OAAO,KAAK,EAAE;AACxB,YAAY,KAAK,CAAC,OAAO,IAAI,CAAC,mBAAmB,EAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9E,YAAY,MAAM,KAAK,CAAC;AACxB,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,0BAA0B,CAAC,UAAU,EAAE,GAAG,EAAE;AAChD,QAAQ,MAAM;AACd,YAAY,aAAa;AACzB,YAAY,kBAAkB;AAC9B,YAAY,qBAAqB;AACjC,YAAY,0BAA0B;AACtC,SAAS,GAAGK,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvC;AACA,QAAQ,IAAI,UAAU,KAAK,oBAAoB,EAAE;AACjD,YAAY,MAAM,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;AACvD;AACA,YAAY,IAAI,0BAA0B,EAAE;AAC5C,gBAAgB,IAAI,OAAO,0BAA0B,KAAK,UAAU,EAAE;AACtE,oBAAoB,MAAM,IAAI,KAAK,CAAC,CAAC,0DAA0D,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;AAChI,iBAAiB;AACjB,gBAAgB,OAAO,IAAI,CAAC,oBAAoB,CAAC,0BAA0B,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AAC/G,aAAa;AACb,YAAY,OAAO,IAAI,CAAC,eAAe,CAAC;AACxC,gBAAgB,GAAG,GAAG;AACtB,gBAAgB,IAAI;AACpB,gBAAgB,QAAQ,EAAE,qBAAqB;AAC/C,aAAa,CAAC,CAAC;AACf,SAAS;AACT,QAAQ,IAAI,UAAU,KAAK,YAAY,EAAE;AACzC,YAAY,MAAM,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;AACvD;AACA,YAAY,IAAI,kBAAkB,EAAE;AACpC,gBAAgB,IAAI,OAAO,kBAAkB,KAAK,UAAU,EAAE;AAC9D,oBAAoB,MAAM,IAAI,KAAK,CAAC,CAAC,kDAAkD,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;AAChH,iBAAiB;AACjB,gBAAgB,OAAO,IAAI,CAAC,oBAAoB,CAAC,kBAAkB,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AACvG,aAAa;AACb,YAAY,OAAO,IAAI,CAAC,eAAe,CAAC;AACxC,gBAAgB,GAAG,GAAG;AACtB,gBAAgB,IAAI;AACpB,gBAAgB,QAAQ,EAAE,aAAa;AACvC,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA,QAAQ,MAAM,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;AAChF,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,yBAAyB,CAAC,UAAU,EAAE,GAAG,EAAE;AAC/C,QAAQ,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACvD;AACA,QAAQ,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE;AAC/B,YAAY,MAAM,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACjF,SAAS;AACT;AACA,QAAQ,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC1E,QAAQ,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;AAC5D;AACA,QAAQ,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE;AACpC,YAAY,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;AAC7E,SAAS;AACT;AACA,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AACzD,QAAQ,MAAM,UAAU;AACxB,YAAY,MAAM,CAAC,UAAU;AAC7B,YAAY,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAClD;AACA,QAAQ,IAAI,UAAU,EAAE;AACxB,YAAY,OAAO,IAAI,CAAC,oBAAoB,CAAC,UAAU,EAAE;AACzD,gBAAgB,GAAG,GAAG;AACtB,gBAAgB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ;AACzD,gBAAgB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AACvE,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA,QAAQ,MAAM,MAAM,CAAC,KAAK,IAAI,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;AACpG,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,4BAA4B,CAAC,UAAU,EAAE,GAAG,EAAE;AAClD,QAAQ,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAGA,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7D,QAAQ,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,IAAIH,wBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;AAChF,QAAQ,IAAI,OAAO,CAAC;AACpB;AACA,QAAQ,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE;AACpC,YAAY,OAAO,GAAG,UAAU,CAAC;AACjC,SAAS,MAAM,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC/C,YAAY,OAAO,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;AACxC,SAAS,MAAM;AACf,YAAY,OAAO,GAAGiB,oBAA2B;AACjD,gBAAgB,UAAU;AAC1B,gBAAgB,eAAe;AAC/B,aAAa,CAAC;AACd,SAAS;AACT;AACA,QAAQ,IAAI,QAAQ,CAAC;AACrB;AACA,QAAQ,IAAI;AACZ,YAAY,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7D,SAAS,CAAC,OAAO,KAAK,EAAE;AACxB;AACA,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE;AAC5D,gBAAgB,MAAM,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;AAC5F,aAAa;AACb,YAAY,MAAM,KAAK,CAAC;AACxB,SAAS;AACT;AACA,QAAQ,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAC/D,QAAQ,OAAO,IAAI,CAAC,eAAe,CAAC;AACpC,YAAY,GAAG,GAAG;AAClB,YAAY,QAAQ;AACpB,YAAY,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC5C,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE;AAC7B,QAAQ,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK;AAC3C,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE;AAClC,gBAAgB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC7E,aAAa;AACb,YAAY,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACvD;AACA,YAAY,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;AACpC;AACA,YAAY,OAAO,GAAG,CAAC;AACvB,SAAS,EAAE,EAAE,CAAC,CAAC;AACf,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE;AACjC,QAAQnB,OAAK,CAAC,2BAA2B,EAAE,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;AACrE;AACA,QAAQ,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAGK,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7D,QAAQ,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,IAAIH,wBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;AAChF;AACA,QAAQ,IAAI;AACZ,YAAY,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACtE;AACA,YAAY,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AACtE;AACA,YAAY,OAAO,IAAI,gBAAgB,CAAC;AACxC,gBAAgB,UAAU,EAAEW,SAAO,CAAC,QAAQ,CAAC;AAC7C,gBAAgB,QAAQ;AACxB,gBAAgB,EAAE,EAAE,UAAU;AAC9B,gBAAgB,YAAY,EAAE,GAAG,CAAC,IAAI;AACtC,gBAAgB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC1C,aAAa,CAAC,CAAC;AACf,SAAS,CAAC,OAAO,KAAK,EAAE;AACxB;AACA;AACA,YAAY,IAAI,UAAU,KAAK,QAAQ,EAAE;AACzC,gBAAgBb,OAAK,CAAC,kBAAkB,CAAC,CAAC;AAC1C,gBAAgB,OAAO,IAAI,gBAAgB,CAAC;AAC5C,oBAAoB,UAAU,EAAEa,SAAO,CAAC,QAAQ,CAAC;AACjD,oBAAoB,QAAQ,EAAEA,SAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;AACvD,oBAAoB,EAAE,EAAE,UAAU;AAClC,oBAAoB,YAAY,EAAE,GAAG,CAAC,IAAI;AAC1C,oBAAoB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC9C,iBAAiB,CAAC,CAAC;AACnB,aAAa;AACb;AACA,YAAYb,OAAK,CAAC,8CAA8C,EAAE,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;AACxF,YAAY,KAAK,CAAC,OAAO,GAAG,CAAC,uBAAuB,EAAE,UAAU,CAAC,eAAe,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AAChH;AACA,YAAY,OAAO,IAAI,gBAAgB,CAAC;AACxC,gBAAgB,KAAK;AACrB,gBAAgB,EAAE,EAAE,UAAU;AAC9B,gBAAgB,YAAY,EAAE,GAAG,CAAC,IAAI;AACtC,gBAAgB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC1C,aAAa,CAAC,CAAC;AACf,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE;AAC3B,QAAQA,OAAK,CAAC,2BAA2B,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/D;AACA,QAAQ,MAAM,EAAE,oBAAoB,EAAE,QAAQ,EAAE,GAAGK,kBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9E,QAAQ,MAAM,OAAO,GAAGc,oBAA2B,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;AAC3E,QAAQ,MAAM,EAAE,GAAGC,gBAAuB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AACrE,QAAQ,MAAM,UAAU,GAAGlB,wBAAI,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,oBAAoB,CAAC,CAAC;AAC/E;AACA,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;AAChC,YAAY,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM;AACvC,gBAAgB,IAAI,KAAK,CAAC,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACtE,gBAAgB;AAChB,oBAAoB,eAAe,EAAE,kBAAkB;AACvD,oBAAoB,WAAW,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE;AACxD,iBAAiB;AACjB,aAAa,CAAC;AACd;AACA,YAAY,OAAO,IAAI,gBAAgB,CAAC;AACxC,gBAAgB,KAAK;AACrB,gBAAgB,EAAE;AAClB,gBAAgB,YAAY,EAAE,GAAG,CAAC,IAAI;AACtC,gBAAgB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC1C,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA;AACA,QAAQ,MAAM,MAAM;AACpB,YAAY,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC;AAC7C,YAAY,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACzC;AACA,QAAQ,IAAI,MAAM,EAAE;AACpB,YAAY,OAAO,IAAI,gBAAgB,CAAC;AACxC,gBAAgB,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC;AACnD,gBAAgB,QAAQ,EAAE,EAAE;AAC5B,gBAAgB,EAAE;AAClB,gBAAgB,YAAY,EAAE,GAAG,CAAC,IAAI;AACtC,gBAAgB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC1C,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA,QAAQ,IAAI,QAAQ,CAAC;AACrB,QAAQ,IAAI,KAAK,CAAC;AAClB;AACA,QAAQ,IAAI;AACZ,YAAY,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7D,SAAS,CAAC,OAAO,YAAY,EAAE;AAC/B,YAAY,KAAK,GAAG,YAAY,CAAC;AACjC;AACA,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE;AAC5D,gBAAgB,KAAK,CAAC,eAAe,GAAG,gBAAgB,CAAC;AACzD,gBAAgB,KAAK,CAAC,WAAW,GAAG;AACpC,oBAAoB,UAAU,EAAE,OAAO;AACvC,oBAAoB,wBAAwB,EAAE,GAAG,CAAC,cAAc;AAChE,oBAAoB,YAAY,EAAE,GAAG,CAAC,IAAI;AAC1C,iBAAiB,CAAC;AAClB,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,QAAQ,EAAE;AACtB,YAAY,IAAI;AAChB,gBAAgB,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AACvE;AACA,gBAAgB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC7C,gBAAgB,MAAM,gBAAgB,GAAGW,SAAO,CAAC,QAAQ,CAAC,CAAC;AAC3D;AACA,gBAAgBb,OAAK,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;AACnF;AACA,gBAAgB,OAAO,IAAI,gBAAgB,CAAC;AAC5C,oBAAoB,UAAU,EAAE,eAAe,CAAC,gBAAgB,CAAC;AACjE,oBAAoB,QAAQ;AAC5B,oBAAoB,EAAE;AACtB,oBAAoB,YAAY,EAAE,GAAG,CAAC,IAAI;AAC1C,oBAAoB,YAAY,EAAE,GAAG,CAAC,QAAQ;AAC9C,iBAAiB,CAAC,CAAC;AACnB,aAAa,CAAC,OAAO,SAAS,EAAE;AAChC,gBAAgB,KAAK,GAAG,SAAS,CAAC;AAClC,aAAa;AACb,SAAS;AACT;AACA,QAAQA,OAAK,CAAC,8CAA8C,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;AAC9E,QAAQ,KAAK,CAAC,OAAO,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;AACtG,QAAQ,OAAO,IAAI,gBAAgB,CAAC;AACpC,YAAY,KAAK;AACjB,YAAY,EAAE;AACd,YAAY,YAAY,EAAE,GAAG,CAAC,IAAI;AAClC,YAAY,YAAY,EAAE,GAAG,CAAC,QAAQ;AACtC,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,CAAC,4BAA4B,CAAC,OAAO,EAAE,GAAG,EAAE;AAChD,QAAQ,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACrD,YAAY,MAAM,UAAU;AAC5B,gBAAgB,OAAO,CAAC,QAAQ,CAAC;AACjC,gBAAgB,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU;AAC5C,gBAAgB,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;AACxD;AACA,YAAY,IAAI,CAAC,UAAU,EAAE;AAC7B,gBAAgB,SAAS;AACzB,aAAa;AACb;AACA,YAAY,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AAC/D,gBAAgB,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACjD,oBAAoB,OAAO,IAAI,CAAC,0BAA0B;AAC1D,wBAAwB;AACxB,4BAA4B,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;AACtD,4BAA4B,SAAS,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;AACnE,yBAAyB;AACzB,wBAAwB;AACxB,4BAA4B,GAAG,GAAG;AAClC,4BAA4B,IAAI,EAAE,oBAAoB;AACtD,4BAA4B,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;AACxF,yBAAyB;AACzB,qBAAqB,CAAC;AACtB,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,KAAK;AACL;;AC1nCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAkBA;AACA,MAAMA,OAAK,GAAGC,6BAAS,CAAC,yCAAyC,CAAC,CAAC;AACnE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB,GAAG,IAAI,OAAO,EAAE,CAAC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,qBAAqB,CAAC;AAC/B,IAAI,kBAAkB;AACtB,IAAI,cAAc;AAClB,IAAI,SAAS;AACb,IAAI,GAAG;AACP,IAAI,SAAS;AACb,CAAC,EAAE;AACH,IAAI,MAAM,eAAe,GAAG,kBAAkB,CAAC,MAAM;AACrD,QAAQ,cAAc;AACtB,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE;AAC9B,KAAK,CAAC;AACN;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM;AACrD,QAAQ,EAAE,cAAc,EAAE,aAAa,CAAC,eAAe,EAAE;AACzD,QAAQ,EAAE,IAAI,EAAE,sBAAsB,EAAE;AACxC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACV;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAC3C,QAAQ,eAAe,CAAC,IAAI,CAAC;AAC7B,YAAY,IAAI,EAAE,QAAQ;AAC1B,YAAY,IAAI,EAAE,YAAY;AAC9B,YAAY,QAAQ,EAAE,EAAE;AACxB,YAAY,OAAO,EAAE;AACrB,gBAAgB,EAAE,EAAE,IAAI,gBAAgB,CAAC;AACzC,oBAAoB,UAAU,EAAE;AAChC,wBAAwB,KAAK,EAAE,SAAS,CAAC,MAAM;AAC/C,4BAA4B,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,CAAC,MAAM;AAC7D,gCAAgC,GAAG;AACnC,gCAAgC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC;AACzD,6BAA6B;AAC7B,4BAA4B,EAAE;AAC9B,yBAAyB;AACzB,qBAAqB;AACrB,oBAAoB,QAAQ,EAAE,EAAE;AAChC,oBAAoB,EAAE,EAAE,EAAE;AAC1B,oBAAoB,YAAY,EAAE,YAAY;AAC9C,oBAAoB,YAAY,EAAE,EAAE;AACpC,iBAAiB,CAAC;AAClB,aAAa;AACb,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA,IAAI,OAAO,eAAe,CAAC;AAC3B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC;AAC9B,IAAI,aAAa;AACjB,IAAI,kBAAkB;AACtB,IAAI,GAAG;AACP,IAAI,UAAU;AACd,IAAI,kBAAkB;AACtB,CAAC,EAAE;AACH,IAAI,MAAM,cAAc,GAAG,kBAAkB,CAAC,MAAM;AACpD,QAAQ,aAAa;AACrB,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE;AAC9B,KAAK,CAAC;AACN;AACA,IAAI,cAAc,CAAC,OAAO;AAC1B,QAAQ,IAAI,UAAU;AACtB,cAAc,kBAAkB,CAAC,gBAAgB,CAAC,UAAU,CAAC;AAC7D,cAAc,kBAAkB,CAAC,uBAAuB,EAAE,CAAC;AAC3D,KAAK,CAAC;AACN;AACA,IAAI,IAAI,kBAAkB,EAAE;AAC5B,QAAQ,cAAc,CAAC,OAAO;AAC9B,YAAY,GAAG,kBAAkB,CAAC,QAAQ;AAC1C,gBAAgB,kBAAkB;AAClC,gBAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE;AACnD,aAAa;AACb,SAAS,CAAC;AACV,KAAK;AACL;AACA,IAAI,OAAO,cAAc,CAAC;AAC1B,CAAC;AACD;AACA;AACA;AACA;AACA,MAAM,0BAA0B,SAAS,KAAK,CAAC;AAC/C;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,aAAa,EAAE;AAC/B,QAAQ,KAAK,CAAC,CAAC,iCAAiC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,QAAQ,IAAI,CAAC,eAAe,GAAG,iBAAiB,CAAC;AACjD,QAAQ,IAAI,CAAC,WAAW,GAAG,EAAE,aAAa,EAAE,CAAC;AAC7C,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,MAAM,2BAA2B,CAAC;AAClC;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC;AAChB,QAAQ,oBAAoB,GAAG,IAAI,GAAG,EAAE;AACxC,QAAQ,UAAU,EAAE,cAAc,GAAG,IAAI;AACzC,QAAQ,SAAS,EAAE,aAAa,GAAG,IAAI;AACvC,QAAQ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;AAC3B,QAAQ,UAAU;AAClB,QAAQ,wBAAwB;AAChC,QAAQ,SAAS,GAAG,EAAE;AACtB,QAAQ,kBAAkB,GAAG,IAAI;AACjC,QAAQ,WAAW,GAAG,IAAI;AAC1B,QAAQ,YAAY,GAAG,IAAI,GAAG,EAAE;AAChC,QAAQ,SAAS;AACjB,QAAQ,QAAQ;AAChB,QAAQ,qBAAqB;AAC7B,QAAQ,0BAA0B;AAClC,QAAQ,aAAa;AACrB,QAAQ,kBAAkB;AAC1B,KAAK,GAAG,EAAE,EAAE;AACZ,QAAQ,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAAC;AAC1D,YAAY,oBAAoB;AAChC,YAAY,GAAG;AACf,YAAY,wBAAwB;AACpC,YAAY,YAAY;AACxB,YAAY,QAAQ;AACpB,YAAY,qBAAqB;AACjC,YAAY,0BAA0B;AACtC,YAAY,aAAa;AACzB,YAAY,kBAAkB;AAC9B,SAAS,CAAC,CAAC;AACX;AACA,QAAQ,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE;AACnC,YAAY,eAAe,EAAE,qBAAqB,CAAC;AACnD,gBAAgB,cAAc;AAC9B,gBAAgB,kBAAkB;AAClC,gBAAgB,GAAG;AACnB,gBAAgB,SAAS;AACzB,gBAAgB,SAAS;AACzB,aAAa,CAAC;AACd,YAAY,cAAc;AAC1B,YAAY,cAAc,EAAE,oBAAoB,CAAC;AACjD,gBAAgB,aAAa;AAC7B,gBAAgB,kBAAkB;AAClC,gBAAgB,GAAG;AACnB,gBAAgB,UAAU;AAC1B,gBAAgB,kBAAkB;AAClC,aAAa,CAAC;AACd,YAAY,aAAa;AACzB,YAAY,kBAAkB;AAC9B,YAAY,WAAW,EAAE,IAAI,GAAG,EAAE;AAClC,YAAY,GAAG;AACf,YAAY,aAAa,EAAE,IAAI,OAAO,EAAE;AACxC,YAAY,UAAU;AACtB,YAAY,SAAS;AACrB,YAAY,kBAAkB;AAC9B,YAAY,WAAW;AACvB,YAAY,YAAY;AACxB,YAAY,SAAS;AACrB,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,GAAG,GAAG;AACd,QAAQ,MAAM,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACnD;AACA,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,QAAQ,EAAE,EAAE,mBAAmB,GAAG,KAAK,EAAE,GAAG,EAAE,EAAE;AAC1E,QAAQ,MAAM;AACd,YAAY,eAAe;AAC3B,YAAY,cAAc;AAC1B,YAAY,GAAG;AACf,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvC;AACA,QAAQ,IAAI,CAAC,QAAQ,EAAE;AACvB,YAAY,OAAO,IAAI,WAAW,CAAC,GAAG,eAAe,EAAE,GAAG,cAAc,CAAC,CAAC;AAC1E,SAAS;AACT;AACA,QAAQ,MAAM,aAAa,GAAGC,wBAAI,CAAC,OAAO,CAACA,wBAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AACxE;AACA,QAAQF,OAAK,CAAC,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD;AACA,QAAQ,OAAO,IAAI,CAAC,oBAAoB;AACxC,YAAY,IAAI,CAAC,sBAAsB,CAAC,aAAa,CAAC;AACtD,YAAY,aAAa;AACzB,YAAY,mBAAmB;AAC/B,SAAS,CAAC;AACV,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,iBAAiB,CAAC,UAAU,EAAE;AAClC,QAAQ,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD;AACA,QAAQ,KAAK,CAAC,aAAa,GAAG,UAAU,CAAC;AACzC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,GAAG;AACjB,QAAQ,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjD;AACA,QAAQ,KAAK,CAAC,eAAe,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAC7D,QAAQ,KAAK,CAAC,cAAc,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;AAC3D,QAAQ,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;AAClC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,sBAAsB,CAAC,aAAa,EAAE,qBAAqB,GAAG,KAAK,EAAE;AACzE,QAAQ,MAAM;AACd,YAAY,eAAe;AAC3B,YAAY,kBAAkB;AAC9B,YAAY,WAAW;AACvB,YAAY,GAAG;AACf,YAAY,WAAW;AACvB,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvC;AACA,QAAQ,IAAI,CAAC,WAAW,EAAE;AAC1B,YAAY,OAAO,eAAe,CAAC;AACnC,SAAS;AACT;AACA,QAAQ,IAAI,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACzD;AACA;AACA,QAAQ,IAAI,WAAW,EAAE;AACzB,YAAYA,OAAK,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,YAAY,OAAO,WAAW,CAAC;AAC/B,SAAS;AACT,QAAQA,OAAK,CAAC,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD;AACA,QAAQ,MAAM,QAAQ,GAAGqB,sBAAE,CAAC,OAAO,EAAE,CAAC;AACtC;AACA;AACA,QAAQ,IAAI,aAAa,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ,EAAE;AAC5D,YAAYrB,OAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,YAAY,IAAI,qBAAqB,EAAE;AACvC,gBAAgB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,8BAA8B,CAAC,aAAa,CAAC,CAAC;AAClG;AACA,gBAAgB,IAAI,QAAQ,EAAE;AAC9B,oBAAoB,sBAAsB;AAC1C,wBAAwB,QAAQ;AAChC,wBAAwB,iCAAiC;AACzD,qBAAqB,CAAC;AACtB,iBAAiB;AACjB,aAAa;AACb,YAAY,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AACrE,SAAS;AACT;AACA;AACA,QAAQ,IAAI;AACZ,YAAY,WAAW,GAAG,kBAAkB,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;AAC5E,SAAS,CAAC,OAAO,KAAK,EAAE;AACxB;AACA,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE;AACzC,gBAAgBA,OAAK,CAAC,4CAA4C,CAAC,CAAC;AACpE,gBAAgB,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AACzE,aAAa;AACb,YAAY,MAAM,KAAK,CAAC;AACxB,SAAS;AACT;AACA,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE;AAC5D,YAAYA,OAAK,CAAC,yCAAyC,CAAC,CAAC;AAC7D,YAAY,WAAW,CAAC,OAAO,CAAC,GAAG,eAAe,CAAC,CAAC;AACpD,YAAY,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACjE,SAAS;AACT;AACA;AACA,QAAQ,MAAM,UAAU,GAAGE,wBAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AACvD,QAAQ,MAAM,iBAAiB,GAAG,UAAU,IAAI,UAAU,KAAK,aAAa;AAC5E,cAAc,IAAI,CAAC,sBAAsB;AACzC,gBAAgB,UAAU;AAC1B,gBAAgB,qBAAqB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;AAC/D,aAAa;AACb,cAAc,eAAe,CAAC;AAC9B;AACA,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;AACpC,YAAY,WAAW,CAAC,OAAO,CAAC,GAAG,iBAAiB,CAAC,CAAC;AACtD,SAAS,MAAM;AACf,YAAY,WAAW,GAAG,iBAAiB,CAAC;AAC5C,SAAS;AACT;AACA;AACA,QAAQ,OAAO,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AAC7D,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,aAAa,EAAE,WAAW,EAAE;AAC7C,QAAQ,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3D;AACA,QAAQ,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACnC,QAAQ,WAAW,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACpD;AACA,QAAQ,OAAO,WAAW,CAAC;AAC3B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,oBAAoB,CAAC,WAAW,EAAE,aAAa,EAAE,mBAAmB,EAAE;AAC1E,QAAQ,MAAM;AACd,YAAY,cAAc;AAC1B,YAAY,kBAAkB;AAC9B,YAAY,aAAa;AACzB,YAAY,WAAW;AACvB,YAAY,YAAY;AACxB,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACvC;AACA,QAAQ,IAAI,gBAAgB,GAAG,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC9D;AACA,QAAQ,IAAI,CAAC,gBAAgB,EAAE;AAC/B,YAAY,gBAAgB,GAAG,WAAW,CAAC;AAC3C;AACA;AACA,YAAY;AACZ,gBAAgB,WAAW;AAC3B,gBAAgB,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnD,gBAAgB,cAAc,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtD,cAAc;AACd,gBAAgB,MAAM,QAAQ,GAAGmB,sBAAE,CAAC,OAAO,EAAE,CAAC;AAC9C;AACA,gBAAgBrB,OAAK,CAAC,gDAAgD,EAAE,QAAQ,CAAC,CAAC;AAClF;AACA,gBAAgB,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,eAAe;AAC9E,oBAAoB,QAAQ;AAC5B,oBAAoB,EAAE,IAAI,EAAE,gBAAgB,EAAE;AAC9C,iBAAiB,CAAC;AAClB;AACA,gBAAgB;AAChB,oBAAoB,mBAAmB,CAAC,MAAM,GAAG,CAAC;AAClD,oBAAoB,CAAC,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC;AACvD,kBAAkB;AAClB,oBAAoB,MAAM,WAAW;AACrC,wBAAwB,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC5E;AACA,oBAAoB,sBAAsB;AAC1C,wBAAwB,WAAW,CAAC,QAAQ;AAC5C,wBAAwB,6BAA6B;AACrD,qBAAqB,CAAC;AACtB,iBAAiB;AACjB;AACA,gBAAgB,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAChF,aAAa;AACb;AACA;AACA,YAAY,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;AAC3C,gBAAgB,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAC3E,aAAa;AACb;AACA;AACA,YAAY,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC;AAClD,gBAAgB,YAAY;AAC5B,aAAa,CAAC,CAAC;AACf;AACA,YAAY,SAAS,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;AAC5D;AACA;AACA,YAAY,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC5C,YAAY,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAC7D;AACA,YAAYA,OAAK;AACjB,gBAAgB,wCAAwC;AACxD,gBAAgB,gBAAgB;AAChC,gBAAgB,aAAa;AAC7B,aAAa,CAAC;AACd,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,mBAAmB,IAAI,WAAW,IAAI,gBAAgB,CAAC,MAAM,IAAI,CAAC,EAAE;AACjF,YAAY,MAAM,IAAI,0BAA0B,CAAC,aAAa,CAAC,CAAC;AAChE,SAAS;AACT;AACA,QAAQ,OAAO,gBAAgB,CAAC;AAChC,KAAK;AACL;;AC7gBA;AACA;AACA;AACA;AAWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,KAAK,GAAGsB,6BAAW,CAAC,sBAAsB,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,iBAAiB,CAAC,cAAc,EAAE;AAC3C,IAAI,uBAAuB;AAC3B,IAAI,wBAAwB;AAC5B,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AACpB,CAAC,EAAE;AACH;AACA,IAAI,MAAM,UAAU,GAAG,EAAE,CAAC;AAC1B,IAAI,MAAM,OAAO,GAAG,EAAE,CAAC;AACvB,IAAI,MAAM,eAAe,GAAG,EAAE,CAAC;AAC/B,IAAI,MAAM,aAAa,GAAG,EAAE,CAAC;AAC7B,IAAI,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;AAC1D,IAAI,MAAM,yBAAyB,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;AAC7E,IAAI,MAAM,uBAAuB,GAAG,CAAC,gBAAgB,EAAE,+BAA+B,CAAC,CAAC;AACxF;AACA;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAClC,QAAQ,IAAI,GAAG,IAAI,cAAc,IAAI,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE;AACjF,YAAY,UAAU,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;AAClD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,yBAAyB,EAAE;AACjD,QAAQ,IAAI,GAAG,IAAI,cAAc,IAAI,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE;AACjF;AACA;AACA,YAAY,UAAU,CAAC,eAAe,GAAG,eAAe,CAAC;AACzD;AACA,YAAY,IAAI,GAAG,KAAK,QAAQ,EAAE;AAClC,gBAAgB,KAAK,CAAC,CAAC,kBAAkB,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC;AAC3G;AACA,gBAAgB,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE;AAC/C,oBAAoB,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACpD,iBAAiB;AACjB;AACA,gBAAgB,eAAe,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;AACtE,gBAAgB,SAAS;AACzB,aAAa;AACb;AACA;AACA,YAAY,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,QAAQ,EAAE;AAChF,gBAAgB,eAAe,CAAC,GAAG,CAAC,GAAG;AACvC,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC;AAC1C,iBAAiB,CAAC;AAClB,aAAa,MAAM;AACnB,gBAAgB,eAAe,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;AAC3D,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,KAAK,MAAM,GAAG,IAAI,uBAAuB,EAAE;AAC/C,QAAQ,IAAI,GAAG,IAAI,cAAc,IAAI,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,WAAW,EAAE;AACjF,YAAY,UAAU,CAAC,aAAa,GAAG,aAAa,CAAC;AACrD,YAAY,aAAa,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;AACrD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,IAAI,eAAe,CAAC,aAAa,EAAE;AACvC;AACA,QAAQ,IAAI,aAAa,IAAI,eAAe,CAAC,aAAa,EAAE;AAC5D,YAAY,eAAe,CAAC,WAAW,GAAG,eAAe,CAAC,aAAa,CAAC,WAAW,CAAC;AACpF,YAAY,OAAO,eAAe,CAAC,aAAa,CAAC,WAAW,CAAC;AAC7D,SAAS;AACT;AACA,QAAQ,IAAI,YAAY,IAAI,eAAe,CAAC,aAAa,EAAE;AAC3D,YAAY,eAAe,CAAC,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,UAAU,CAAC;AAClF,YAAY,OAAO,eAAe,CAAC,aAAa,CAAC,UAAU,CAAC;AAC5D,SAAS;AACT;AACA;AACA,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;AACrE,YAAY,OAAO,eAAe,CAAC,aAAa,CAAC;AACjD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,IAAI,cAAc,CAAC,QAAQ,EAAE;AACjC,QAAQ,UAAU,CAAC,KAAK,GAAG,CAAC,gBAAgB,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChG,KAAK;AACL;AACA;AACA,IAAI,IAAI,cAAc,CAAC,OAAO,IAAI,OAAO,cAAc,CAAC,OAAO,KAAK,QAAQ,EAAE;AAC9E,QAAQ,KAAK,CAAC,CAAC,qBAAqB,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAChE;AACA,QAAQ,UAAU,CAAC,OAAO,GAAG,EAAE,CAAC;AAChC;AACA,QAAQ,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE;AACtE;AACA,YAAY,KAAK,CAAC,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;AACvD,YAAY,KAAK,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,aAAa,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC;AAC7F;AACA,YAAY,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AACrF;AACA,YAAY,IAAI,KAAK,EAAE;AACvB,gBAAgB,MAAM,KAAK,CAAC;AAC5B,aAAa;AACb;AACA,YAAY,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC;AACpD;AACA;AACA,YAAY,IAAI,MAAM,CAAC,UAAU,EAAE;AACnC,gBAAgB,KAAK,MAAM,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AAC5E,oBAAoB,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACvD,wBAAwB,KAAK,CAAC,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;AACrF;AACA,wBAAwB,OAAO,CAAC,OAAO,CAAC;AACxC,4BAA4B,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;AAC3D,4BAA4B,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;AAC7F,yBAAyB,CAAC,CAAC;AAC3B,qBAAqB;AACrB;AACA,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,IAAI,cAAc,CAAC,GAAG,IAAI,OAAO,cAAc,CAAC,GAAG,KAAK,QAAQ,EAAE;AACtE,QAAQ,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;AAC/D;AACA;AACA,YAAY,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AAC7C,gBAAgB,KAAK,CAAC,CAAC,yBAAyB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7D;AACA,gBAAgB,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AAC/C;AACA;AACA,oBAAoB,OAAO,CAAC,OAAO,CAAC,GAAG,iBAAiB,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AACpF,wBAAwB,uBAAuB;AAC/C,wBAAwB,wBAAwB;AAChD,qBAAqB,CAAC,CAAC,CAAC;AACxB,iBAAiB,MAAM,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AAC5D;AACA;AACA,oBAAoB,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AACvF,wBAAwB,uBAAuB;AAC/C,wBAAwB,wBAAwB;AAChD,qBAAqB,CAAC,CAAC,CAAC;AACxB,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;AAC5C,QAAQ,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACjC,KAAK;AACL;AACA,IAAI,OAAO,OAAO,CAAC;AACnB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,UAAU,CAAC;AACjB;AACA,IAAI,WAAW,CAAC;AAChB,QAAQ,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;AACrC,QAAQ,wBAAwB,GAAG,aAAa;AAChD,QAAQ,iBAAiB;AACzB,QAAQ,SAAS;AACjB,KAAK,GAAG,EAAE,EAAE;AACZ,QAAQ,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;AAC3C,QAAQ,IAAI,CAAC,wBAAwB,GAAG,wBAAwB,CAAC;AACjE,QAAQ,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,kBAAkB,CAAC;AACjD,YAAY,GAAG,EAAE,aAAa;AAC9B,YAAY,wBAAwB;AACpC,YAAY,kBAAkB,EAAE,MAAM;AACtC;AACA,gBAAgB,IAAI,CAAC,SAAS,EAAE;AAChC,oBAAoB,MAAM,IAAI,SAAS,CAAC,0DAA0D,CAAC,CAAC;AACpG,iBAAiB;AACjB;AACA,gBAAgB,OAAO,SAAS,CAAC;AACjC,aAAa;AACb,YAAY,0BAA0B,EAAE,MAAM;AAC9C;AACA,gBAAgB,IAAI,CAAC,iBAAiB,EAAE;AACxC,oBAAoB,MAAM,IAAI,SAAS,CAAC,kEAAkE,CAAC,CAAC;AAC5G,iBAAiB;AACjB;AACA,gBAAgB,OAAO,iBAAiB,CAAC;AACzC,aAAa;AACb,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,cAAc,EAAE;AAC3B,QAAQ,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE;AACrE,YAAY,QAAQ,EAAE,IAAI,CAAC,aAAa;AACxC,SAAS,CAAC,CAAC;AACX;AACA,QAAQ,MAAM,SAAS,GAAG,EAAE,CAAC;AAC7B,QAAQ,IAAI,iBAAiB,GAAG,KAAK,CAAC;AACtC;AACA,QAAQ,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI;AAC5C,YAAY,IAAI,UAAU,CAAC,IAAI,KAAK,QAAQ,EAAE;AAC9C,gBAAgB,iBAAiB,GAAG,iBAAiB,IAAI,UAAU,CAAC,aAAa,CAAC;AAClF,gBAAgB,SAAS,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,UAAU,EAAE;AAChE,oBAAoB,uBAAuB,EAAEpB,wBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC;AAC9F,oBAAoB,wBAAwB,EAAEA,wBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,kBAAkB,CAAC;AAC1G,oBAAoB,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;AACxE,oBAAoB,gBAAgB,EAAE,aAAa,CAAC,gBAAgB;AACpE,iBAAiB,CAAC,CAAC,CAAC;AACpB,aAAa;AACb,SAAS,CAAC,CAAC;AACX;AACA;AACA,QAAQ,IAAI,iBAAiB,EAAE;AAC/B,YAAY,SAAS,CAAC,OAAO,CAAC;AAC9B,gBAAgB,OAAO,EAAE,CAAC,QAAQ,IAAI;AACtC;AACA;AACA;AACA,oBAAoB,MAAM,WAAW,GAAG,aAAa,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AAC9E;AACA;AACA,oBAAoB,OAAO,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACzF,iBAAiB,CAAC;AAClB,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA,QAAQ,OAAO,SAAS,CAAC;AACzB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,SAAS,EAAE;AACnB,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC;AAC3B,YAAY,GAAG,EAAE,SAAS;AAC1B,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,GAAG,eAAe,EAAE;AAChC,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC;AAC3B,YAAY,OAAO,EAAE,eAAe;AACpC,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,GAAG,OAAO,EAAE;AACxB,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC;AAC3B,YAAY,OAAO;AACnB,SAAS,CAAC,CAAC;AACX,KAAK;AACL;;ACrTA;AACA;AACA;AACA;AAsBA;AACA;AACA;AACA;AACA;AACK,MAAC,MAAM,GAAG;AACf,IAAI,WAAW;AACf,qCAAIqB,aAA+B;AACnC,IAAI,2BAA2B;AAC/B,IAAI,kBAAkB;AACtB,IAAI,gBAAgB;AACpB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,cAAc;AAClB,IAAI,uBAAuB;AAC3B,IAAI,YAAY;AAChB;AACA;AACA,IAAI,SAAS;AACb,IAAI,eAAe;AACnB,IAAI,cAAc;AAClB,IAAI,MAAM;AACV;;;;;"} +\ No newline at end of file ++{"version":3,"file":"eslintrc.cjs","sources":["../lib/config-array/ignore-pattern.js","../lib/config-array/extracted-config.js","../lib/config-array/config-array.js","../lib/config-array/config-dependency.js","../lib/config-array/override-tester.js","../lib/config-array/index.js","../lib/shared/config-ops.js","../lib/shared/deprecation-warnings.js","../lib/shared/ajv.js","../conf/config-schema.js","../conf/environments.js","../lib/shared/config-validator.js","../lib/shared/naming.js","../lib/shared/relative-module-resolver.js","../lib/config-array-factory.js","../lib/cascading-config-array-factory.js","../lib/flat-compat.js","../lib/index.js"],"sourcesContent":["/**\n * @fileoverview `IgnorePattern` class.\n *\n * `IgnorePattern` class has the set of glob patterns and the base path.\n *\n * It provides two static methods.\n *\n * - `IgnorePattern.createDefaultIgnore(cwd)`\n * Create the default predicate function.\n * - `IgnorePattern.createIgnore(ignorePatterns)`\n * Create the predicate function from multiple `IgnorePattern` objects.\n *\n * It provides two properties and a method.\n *\n * - `patterns`\n * The glob patterns that ignore to lint.\n * - `basePath`\n * The base path of the glob patterns. If absolute paths existed in the\n * glob patterns, those are handled as relative paths to the base path.\n * - `getPatternsRelativeTo(basePath)`\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n *\n * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes\n * `ignorePatterns` properties.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport ignore from \"ignore\";\nimport debugOrig from \"debug\";\n\nconst debug = debugOrig(\"eslintrc:ignore-pattern\");\n\n/** @typedef {ReturnType} Ignore */\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the path to the common ancestor directory of given paths.\n * @param {string[]} sourcePaths The paths to calculate the common ancestor.\n * @returns {string} The path to the common ancestor directory.\n */\nfunction getCommonAncestorPath(sourcePaths) {\n let result = sourcePaths[0];\n\n for (let i = 1; i < sourcePaths.length; ++i) {\n const a = result;\n const b = sourcePaths[i];\n\n // Set the shorter one (it's the common ancestor if one includes the other).\n result = a.length < b.length ? a : b;\n\n // Set the common ancestor.\n for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {\n if (a[j] !== b[j]) {\n result = a.slice(0, lastSepPos);\n break;\n }\n if (a[j] === path.sep) {\n lastSepPos = j;\n }\n }\n }\n\n let resolvedResult = result || path.sep;\n\n // if Windows common ancestor is root of drive must have trailing slash to be absolute.\n if (resolvedResult && resolvedResult.endsWith(\":\") && process.platform === \"win32\") {\n resolvedResult += path.sep;\n }\n return resolvedResult;\n}\n\n/**\n * Make relative path.\n * @param {string} from The source path to get relative path.\n * @param {string} to The destination path to get relative path.\n * @returns {string} The relative path.\n */\nfunction relative(from, to) {\n const relPath = path.relative(from, to);\n\n if (path.sep === \"/\") {\n return relPath;\n }\n return relPath.split(path.sep).join(\"/\");\n}\n\n/**\n * Get the trailing slash if existed.\n * @param {string} filePath The path to check.\n * @returns {string} The trailing slash if existed.\n */\nfunction dirSuffix(filePath) {\n const isDir = (\n filePath.endsWith(path.sep) ||\n (process.platform === \"win32\" && filePath.endsWith(\"/\"))\n );\n\n return isDir ? \"/\" : \"\";\n}\n\nconst DefaultPatterns = Object.freeze([\"/**/node_modules/*\"]);\nconst DotPatterns = Object.freeze([\".*\", \"!.eslintrc.*\", \"!../\"]);\n\n//------------------------------------------------------------------------------\n// Public\n//------------------------------------------------------------------------------\n\nclass IgnorePattern {\n\n /**\n * The default patterns.\n * @type {string[]}\n */\n static get DefaultPatterns() {\n return DefaultPatterns;\n }\n\n /**\n * Create the default predicate function.\n * @param {string} cwd The current working directory.\n * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createDefaultIgnore(cwd) {\n return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);\n }\n\n /**\n * Create the predicate function from multiple `IgnorePattern` objects.\n * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.\n * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}\n * The preficate function.\n * The first argument is an absolute path that is checked.\n * The second argument is the flag to not ignore dotfiles.\n * If the predicate function returned `true`, it means the path should be ignored.\n */\n static createIgnore(ignorePatterns) {\n debug(\"Create with: %o\", ignorePatterns);\n\n const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));\n const patterns = [].concat(\n ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))\n );\n const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);\n const dotIg = ignore({ allowRelativePaths: true }).add(patterns);\n\n debug(\" processed: %o\", { basePath, patterns });\n\n return Object.assign(\n (filePath, dot = false) => {\n assert(path.isAbsolute(filePath), \"'filePath' should be an absolute path.\");\n const relPathRaw = relative(basePath, filePath);\n const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));\n const adoptedIg = dot ? dotIg : ig;\n const result = relPath !== \"\" && adoptedIg.ignores(relPath);\n\n debug(\"Check\", { filePath, dot, relativePath: relPath, result });\n return result;\n },\n { basePath, patterns }\n );\n }\n\n /**\n * Initialize a new `IgnorePattern` instance.\n * @param {string[]} patterns The glob patterns that ignore to lint.\n * @param {string} basePath The base path of `patterns`.\n */\n constructor(patterns, basePath) {\n assert(path.isAbsolute(basePath), \"'basePath' should be an absolute path.\");\n\n /**\n * The glob patterns that ignore to lint.\n * @type {string[]}\n */\n this.patterns = patterns;\n\n /**\n * The base path of `patterns`.\n * @type {string}\n */\n this.basePath = basePath;\n\n /**\n * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.\n *\n * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.\n * It's `false` as-is for `ignorePatterns` property in config files.\n * @type {boolean}\n */\n this.loose = false;\n }\n\n /**\n * Get `patterns` as modified for a given base path. It modifies the\n * absolute paths in the patterns as prepending the difference of two base\n * paths.\n * @param {string} newBasePath The base path.\n * @returns {string[]} Modifired patterns.\n */\n getPatternsRelativeTo(newBasePath) {\n assert(path.isAbsolute(newBasePath), \"'newBasePath' should be an absolute path.\");\n const { basePath, loose, patterns } = this;\n\n if (newBasePath === basePath) {\n return patterns;\n }\n const prefix = `/${relative(newBasePath, basePath)}`;\n\n return patterns.map(pattern => {\n const negative = pattern.startsWith(\"!\");\n const head = negative ? \"!\" : \"\";\n const body = negative ? pattern.slice(1) : pattern;\n\n if (body.startsWith(\"/\") || body.startsWith(\"../\")) {\n return `${head}${prefix}${body}`;\n }\n return loose ? pattern : `${head}${prefix}/**/${body}`;\n });\n }\n}\n\nexport { IgnorePattern };\n","/**\n * @fileoverview `ExtractedConfig` class.\n *\n * `ExtractedConfig` class expresses a final configuration for a specific file.\n *\n * It provides one method.\n *\n * - `toCompatibleObjectAsConfigFileContent()`\n * Convert this configuration to the compatible object as the content of\n * config files. It converts the loaded parser and plugins to strings.\n * `CLIEngine#getConfigForFile(filePath)` method uses this method.\n *\n * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.\n *\n * @author Toru Nagashima \n */\n\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n// For VSCode intellisense\n/** @typedef {import(\"../../shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").SeverityConf} SeverityConf */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n\n/**\n * Check if `xs` starts with `ys`.\n * @template T\n * @param {T[]} xs The array to check.\n * @param {T[]} ys The array that may be the first part of `xs`.\n * @returns {boolean} `true` if `xs` starts with `ys`.\n */\nfunction startsWith(xs, ys) {\n return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);\n}\n\n/**\n * The class for extracted config data.\n */\nclass ExtractedConfig {\n constructor() {\n\n /**\n * The config name what `noInlineConfig` setting came from.\n * @type {string}\n */\n this.configNameOfNoInlineConfig = \"\";\n\n /**\n * Environments.\n * @type {Record}\n */\n this.env = {};\n\n /**\n * Global variables.\n * @type {Record}\n */\n this.globals = {};\n\n /**\n * The glob patterns that ignore to lint.\n * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}\n */\n this.ignores = void 0;\n\n /**\n * The flag that disables directive comments.\n * @type {boolean|undefined}\n */\n this.noInlineConfig = void 0;\n\n /**\n * Parser definition.\n * @type {DependentParser|null}\n */\n this.parser = null;\n\n /**\n * Options for the parser.\n * @type {Object}\n */\n this.parserOptions = {};\n\n /**\n * Plugin definitions.\n * @type {Record}\n */\n this.plugins = {};\n\n /**\n * Processor ID.\n * @type {string|null}\n */\n this.processor = null;\n\n /**\n * The flag that reports unused `eslint-disable` directive comments.\n * @type {boolean|undefined}\n */\n this.reportUnusedDisableDirectives = void 0;\n\n /**\n * Rule settings.\n * @type {Record}\n */\n this.rules = {};\n\n /**\n * Shared settings.\n * @type {Object}\n */\n this.settings = {};\n }\n\n /**\n * Convert this config to the compatible object as a config file content.\n * @returns {ConfigData} The converted object.\n */\n toCompatibleObjectAsConfigFileContent() {\n const {\n /* eslint-disable no-unused-vars */\n configNameOfNoInlineConfig: _ignore1,\n processor: _ignore2,\n /* eslint-enable no-unused-vars */\n ignores,\n ...config\n } = this;\n\n config.parser = config.parser && config.parser.filePath;\n config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();\n config.ignorePatterns = ignores ? ignores.patterns : [];\n\n // Strip the default patterns from `ignorePatterns`.\n if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {\n config.ignorePatterns =\n config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);\n }\n\n return config;\n }\n}\n\nexport { ExtractedConfig };\n","/**\n * @fileoverview `ConfigArray` class.\n *\n * `ConfigArray` class expresses the full of a configuration. It has the entry\n * config file, base config files that were extended, loaded parsers, and loaded\n * plugins.\n *\n * `ConfigArray` class provides three properties and two methods.\n *\n * - `pluginEnvironments`\n * - `pluginProcessors`\n * - `pluginRules`\n * The `Map` objects that contain the members of all plugins that this\n * config array contains. Those map objects don't have mutation methods.\n * Those keys are the member ID such as `pluginId/memberName`.\n * - `isRoot()`\n * If `true` then this configuration has `root:true` property.\n * - `extractConfig(filePath)`\n * Extract the final configuration for a given file. This means merging\n * every config array element which that `criteria` property matched. The\n * `filePath` argument must be an absolute path.\n *\n * `ConfigArrayFactory` provides the loading logic of config files.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").GlobalConf} GlobalConf */\n/** @typedef {import(\"../../shared/types\").RuleConf} RuleConf */\n/** @typedef {import(\"../../shared/types\").Rule} Rule */\n/** @typedef {import(\"../../shared/types\").Plugin} Plugin */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n/** @typedef {import(\"./config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {import(\"./override-tester\")[\"OverrideTester\"]} OverrideTester */\n\n/**\n * @typedef {Object} ConfigArrayElement\n * @property {string} name The name of this config element.\n * @property {string} filePath The path to the source file of this config element.\n * @property {InstanceType|null} criteria The tester for the `files` and `excludedFiles` of this config element.\n * @property {Record|undefined} env The environment settings.\n * @property {Record|undefined} globals The global variable settings.\n * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.\n * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.\n * @property {DependentParser|undefined} parser The parser loader.\n * @property {Object|undefined} parserOptions The parser options.\n * @property {Record|undefined} plugins The plugin loaders.\n * @property {string|undefined} processor The processor name to refer plugin's processor.\n * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.\n * @property {boolean|undefined} root The flag to express root.\n * @property {Record|undefined} rules The rule settings\n * @property {Object|undefined} settings The shared settings.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The element type.\n */\n\n/**\n * @typedef {Object} ConfigArrayInternalSlots\n * @property {Map} cache The cache to extract configs.\n * @property {ReadonlyMap|null} envMap The map from environment ID to environment definition.\n * @property {ReadonlyMap|null} processorMap The map from processor ID to environment definition.\n * @property {ReadonlyMap|null} ruleMap The map from rule ID to rule definition.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new class extends WeakMap {\n get(key) {\n let value = super.get(key);\n\n if (!value) {\n value = {\n cache: new Map(),\n envMap: null,\n processorMap: null,\n ruleMap: null\n };\n super.set(key, value);\n }\n\n return value;\n }\n}();\n\n/**\n * Get the indices which are matched to a given file.\n * @param {ConfigArrayElement[]} elements The elements.\n * @param {string} filePath The path to a target file.\n * @returns {number[]} The indices.\n */\nfunction getMatchedIndices(elements, filePath) {\n const indices = [];\n\n for (let i = elements.length - 1; i >= 0; --i) {\n const element = elements[i];\n\n if (!element.criteria || (filePath && element.criteria.test(filePath))) {\n indices.push(i);\n }\n }\n\n return indices;\n}\n\n/**\n * Check if a value is a non-null object.\n * @param {any} x The value to check.\n * @returns {boolean} `true` if the value is a non-null object.\n */\nfunction isNonNullObject(x) {\n return typeof x === \"object\" && x !== null;\n}\n\n/**\n * Merge two objects.\n *\n * Assign every property values of `y` to `x` if `x` doesn't have the property.\n * If `x`'s property value is an object, it does recursive.\n * @param {Object} target The destination to merge\n * @param {Object|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeWithoutOverwrite(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n\n if (isNonNullObject(target[key])) {\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (target[key] === void 0) {\n if (isNonNullObject(source[key])) {\n target[key] = Array.isArray(source[key]) ? [] : {};\n mergeWithoutOverwrite(target[key], source[key]);\n } else if (source[key] !== void 0) {\n target[key] = source[key];\n }\n }\n }\n}\n\n/**\n * The error for plugin conflicts.\n */\nclass PluginConflictError extends Error {\n\n /**\n * Initialize this error object.\n * @param {string} pluginId The plugin ID.\n * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.\n */\n constructor(pluginId, plugins) {\n super(`Plugin \"${pluginId}\" was conflicted between ${plugins.map(p => `\"${p.importerName}\"`).join(\" and \")}.`);\n this.messageTemplate = \"plugin-conflict\";\n this.messageData = { pluginId, plugins };\n }\n}\n\n/**\n * Merge plugins.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergePlugins(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetValue = target[key];\n const sourceValue = source[key];\n\n // Adopt the plugin which was found at first.\n if (targetValue === void 0) {\n if (sourceValue.error) {\n throw sourceValue.error;\n }\n target[key] = sourceValue;\n } else if (sourceValue.filePath !== targetValue.filePath) {\n throw new PluginConflictError(key, [\n {\n filePath: targetValue.filePath,\n importerName: targetValue.importerName\n },\n {\n filePath: sourceValue.filePath,\n importerName: sourceValue.importerName\n }\n ]);\n }\n }\n}\n\n/**\n * Merge rule configs.\n * `target`'s definition is prior to `source`'s.\n * @param {Record} target The destination to merge\n * @param {Record|undefined} source The source to merge.\n * @returns {void}\n */\nfunction mergeRuleConfigs(target, source) {\n if (!isNonNullObject(source)) {\n return;\n }\n\n for (const key of Object.keys(source)) {\n if (key === \"__proto__\") {\n continue;\n }\n const targetDef = target[key];\n const sourceDef = source[key];\n\n // Adopt the rule config which was found at first.\n if (targetDef === void 0) {\n if (Array.isArray(sourceDef)) {\n target[key] = [...sourceDef];\n } else {\n target[key] = [sourceDef];\n }\n\n /*\n * If the first found rule config is severity only and the current rule\n * config has options, merge the severity and the options.\n */\n } else if (\n targetDef.length === 1 &&\n Array.isArray(sourceDef) &&\n sourceDef.length >= 2\n ) {\n targetDef.push(...sourceDef.slice(1));\n }\n }\n}\n\n/**\n * Create the extracted config.\n * @param {ConfigArray} instance The config elements.\n * @param {number[]} indices The indices to use.\n * @returns {ExtractedConfig} The extracted config.\n */\nfunction createConfig(instance, indices) {\n const config = new ExtractedConfig();\n const ignorePatterns = [];\n\n // Merge elements.\n for (const index of indices) {\n const element = instance[index];\n\n // Adopt the parser which was found at first.\n if (!config.parser && element.parser) {\n if (element.parser.error) {\n throw element.parser.error;\n }\n config.parser = element.parser;\n }\n\n // Adopt the processor which was found at first.\n if (!config.processor && element.processor) {\n config.processor = element.processor;\n }\n\n // Adopt the noInlineConfig which was found at first.\n if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {\n config.noInlineConfig = element.noInlineConfig;\n config.configNameOfNoInlineConfig = element.name;\n }\n\n // Adopt the reportUnusedDisableDirectives which was found at first.\n if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {\n config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;\n }\n\n // Collect ignorePatterns\n if (element.ignorePattern) {\n ignorePatterns.push(element.ignorePattern);\n }\n\n // Merge others.\n mergeWithoutOverwrite(config.env, element.env);\n mergeWithoutOverwrite(config.globals, element.globals);\n mergeWithoutOverwrite(config.parserOptions, element.parserOptions);\n mergeWithoutOverwrite(config.settings, element.settings);\n mergePlugins(config.plugins, element.plugins);\n mergeRuleConfigs(config.rules, element.rules);\n }\n\n // Create the predicate function for ignore patterns.\n if (ignorePatterns.length > 0) {\n config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());\n }\n\n return config;\n}\n\n/**\n * Collect definitions.\n * @template T, U\n * @param {string} pluginId The plugin ID for prefix.\n * @param {Record} defs The definitions to collect.\n * @param {Map} map The map to output.\n * @param {function(T): U} [normalize] The normalize function for each value.\n * @returns {void}\n */\nfunction collect(pluginId, defs, map, normalize) {\n if (defs) {\n const prefix = pluginId && `${pluginId}/`;\n\n for (const [key, value] of Object.entries(defs)) {\n map.set(\n `${prefix}${key}`,\n normalize ? normalize(value) : value\n );\n }\n }\n}\n\n/**\n * Normalize a rule definition.\n * @param {Function|Rule} rule The rule definition to normalize.\n * @returns {Rule} The normalized rule definition.\n */\nfunction normalizePluginRule(rule) {\n return typeof rule === \"function\" ? { create: rule } : rule;\n}\n\n/**\n * Delete the mutation methods from a given map.\n * @param {Map} map The map object to delete.\n * @returns {void}\n */\nfunction deleteMutationMethods(map) {\n Object.defineProperties(map, {\n clear: { configurable: true, value: void 0 },\n delete: { configurable: true, value: void 0 },\n set: { configurable: true, value: void 0 }\n });\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArrayElement[]} elements The config elements.\n * @param {ConfigArrayInternalSlots} slots The internal slots.\n * @returns {void}\n */\nfunction initPluginMemberMaps(elements, slots) {\n const processed = new Set();\n\n slots.envMap = new Map();\n slots.processorMap = new Map();\n slots.ruleMap = new Map();\n\n for (const element of elements) {\n if (!element.plugins) {\n continue;\n }\n\n for (const [pluginId, value] of Object.entries(element.plugins)) {\n const plugin = value.definition;\n\n if (!plugin || processed.has(pluginId)) {\n continue;\n }\n processed.add(pluginId);\n\n collect(pluginId, plugin.environments, slots.envMap);\n collect(pluginId, plugin.processors, slots.processorMap);\n collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);\n }\n }\n\n deleteMutationMethods(slots.envMap);\n deleteMutationMethods(slots.processorMap);\n deleteMutationMethods(slots.ruleMap);\n}\n\n/**\n * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.\n * @param {ConfigArray} instance The config elements.\n * @returns {ConfigArrayInternalSlots} The extracted config.\n */\nfunction ensurePluginMemberMaps(instance) {\n const slots = internalSlotsMap.get(instance);\n\n if (!slots.ruleMap) {\n initPluginMemberMaps(instance, slots);\n }\n\n return slots;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The Config Array.\n *\n * `ConfigArray` instance contains all settings, parsers, and plugins.\n * You need to call `ConfigArray#extractConfig(filePath)` method in order to\n * extract, merge and get only the config data which is related to an arbitrary\n * file.\n * @extends {Array}\n */\nclass ConfigArray extends Array {\n\n /**\n * Get the plugin environments.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin environments.\n */\n get pluginEnvironments() {\n return ensurePluginMemberMaps(this).envMap;\n }\n\n /**\n * Get the plugin processors.\n * The returned map cannot be mutated.\n * @type {ReadonlyMap} The plugin processors.\n */\n get pluginProcessors() {\n return ensurePluginMemberMaps(this).processorMap;\n }\n\n /**\n * Get the plugin rules.\n * The returned map cannot be mutated.\n * @returns {ReadonlyMap} The plugin rules.\n */\n get pluginRules() {\n return ensurePluginMemberMaps(this).ruleMap;\n }\n\n /**\n * Check if this config has `root` flag.\n * @returns {boolean} `true` if this config array is root.\n */\n isRoot() {\n for (let i = this.length - 1; i >= 0; --i) {\n const root = this[i].root;\n\n if (typeof root === \"boolean\") {\n return root;\n }\n }\n return false;\n }\n\n /**\n * Extract the config data which is related to a given file.\n * @param {string} filePath The absolute path to the target file.\n * @returns {ExtractedConfig} The extracted config data.\n */\n extractConfig(filePath) {\n const { cache } = internalSlotsMap.get(this);\n const indices = getMatchedIndices(this, filePath);\n const cacheKey = indices.join(\",\");\n\n if (!cache.has(cacheKey)) {\n cache.set(cacheKey, createConfig(this, indices));\n }\n\n return cache.get(cacheKey);\n }\n\n /**\n * Check if a given path is an additional lint target.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the file is an additional lint target.\n */\n isAdditionalTargetPath(filePath) {\n for (const { criteria, type } of this) {\n if (\n type === \"config\" &&\n criteria &&\n !criteria.endsWithWildcard &&\n criteria.test(filePath)\n ) {\n return true;\n }\n }\n return false;\n }\n}\n\n/**\n * Get the used extracted configs.\n * CLIEngine will use this method to collect used deprecated rules.\n * @param {ConfigArray} instance The config array object to get.\n * @returns {ExtractedConfig[]} The used extracted configs.\n * @private\n */\nfunction getUsedExtractedConfigs(instance) {\n const { cache } = internalSlotsMap.get(instance);\n\n return Array.from(cache.values());\n}\n\n\nexport {\n ConfigArray,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview `ConfigDependency` class.\n *\n * `ConfigDependency` class expresses a loaded parser or plugin.\n *\n * If the parser or plugin was loaded successfully, it has `definition` property\n * and `filePath` property. Otherwise, it has `error` property.\n *\n * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it\n * omits `definition` property.\n *\n * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers\n * or plugins.\n *\n * @author Toru Nagashima \n */\n\nimport util from \"util\";\n\n/**\n * The class is to store parsers or plugins.\n * This class hides the loaded object from `JSON.stringify()` and `console.log`.\n * @template T\n */\nclass ConfigDependency {\n\n /**\n * Initialize this instance.\n * @param {Object} data The dependency data.\n * @param {T} [data.definition] The dependency if the loading succeeded.\n * @param {Error} [data.error] The error object if the loading failed.\n * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.\n * @param {string} data.id The ID of this dependency.\n * @param {string} data.importerName The name of the config file which loads this dependency.\n * @param {string} data.importerPath The path to the config file which loads this dependency.\n */\n constructor({\n definition = null,\n error = null,\n filePath = null,\n id,\n importerName,\n importerPath\n }) {\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {T|null}\n */\n this.definition = definition;\n\n /**\n * The error object if the loading failed.\n * @type {Error|null}\n */\n this.error = error;\n\n /**\n * The loaded dependency if the loading succeeded.\n * @type {string|null}\n */\n this.filePath = filePath;\n\n /**\n * The ID of this dependency.\n * @type {string}\n */\n this.id = id;\n\n /**\n * The name of the config file which loads this dependency.\n * @type {string}\n */\n this.importerName = importerName;\n\n /**\n * The path to the config file which loads this dependency.\n * @type {string}\n */\n this.importerPath = importerPath;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n const obj = this[util.inspect.custom]();\n\n // Display `error.message` (`Error#message` is unenumerable).\n if (obj.error instanceof Error) {\n obj.error = { ...obj.error, message: obj.error.message };\n }\n\n return obj;\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n const {\n definition: _ignore, // eslint-disable-line no-unused-vars\n ...obj\n } = this;\n\n return obj;\n }\n}\n\n/** @typedef {ConfigDependency} DependentParser */\n/** @typedef {ConfigDependency} DependentPlugin */\n\nexport { ConfigDependency };\n","/**\n * @fileoverview `OverrideTester` class.\n *\n * `OverrideTester` class handles `files` property and `excludedFiles` property\n * of `overrides` config.\n *\n * It provides one method.\n *\n * - `test(filePath)`\n * Test if a file path matches the pair of `files` property and\n * `excludedFiles` property. The `filePath` argument must be an absolute\n * path.\n *\n * `ConfigArrayFactory` creates `OverrideTester` objects when it processes\n * `overrides` properties.\n *\n * @author Toru Nagashima \n */\n\nimport assert from \"assert\";\nimport path from \"path\";\nimport util from \"util\";\nimport minimatch from \"minimatch\";\n\nconst { Minimatch } = minimatch;\n\nconst minimatchOpts = { dot: true, matchBase: true };\n\n/**\n * @typedef {Object} Pattern\n * @property {InstanceType[] | null} includes The positive matchers.\n * @property {InstanceType[] | null} excludes The negative matchers.\n */\n\n/**\n * Normalize a given pattern to an array.\n * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.\n * @returns {string[]|null} Normalized patterns.\n * @private\n */\nfunction normalizePatterns(patterns) {\n if (Array.isArray(patterns)) {\n return patterns.filter(Boolean);\n }\n if (typeof patterns === \"string\" && patterns) {\n return [patterns];\n }\n return [];\n}\n\n/**\n * Create the matchers of given patterns.\n * @param {string[]} patterns The patterns.\n * @returns {InstanceType[] | null} The matchers.\n */\nfunction toMatcher(patterns) {\n if (patterns.length === 0) {\n return null;\n }\n return patterns.map(pattern => {\n if (/^\\.[/\\\\]/u.test(pattern)) {\n return new Minimatch(\n pattern.slice(2),\n\n // `./*.js` should not match with `subdir/foo.js`\n { ...minimatchOpts, matchBase: false }\n );\n }\n return new Minimatch(pattern, minimatchOpts);\n });\n}\n\n/**\n * Convert a given matcher to string.\n * @param {Pattern} matchers The matchers.\n * @returns {string} The string expression of the matcher.\n */\nfunction patternToJson({ includes, excludes }) {\n return {\n includes: includes && includes.map(m => m.pattern),\n excludes: excludes && excludes.map(m => m.pattern)\n };\n}\n\n/**\n * The class to test given paths are matched by the patterns.\n */\nclass OverrideTester {\n\n /**\n * Create a tester with given criteria.\n * If there are no criteria, returns `null`.\n * @param {string|string[]} files The glob patterns for included files.\n * @param {string|string[]} excludedFiles The glob patterns for excluded files.\n * @param {string} basePath The path to the base directory to test paths.\n * @returns {OverrideTester|null} The created instance or `null`.\n */\n static create(files, excludedFiles, basePath) {\n const includePatterns = normalizePatterns(files);\n const excludePatterns = normalizePatterns(excludedFiles);\n let endsWithWildcard = false;\n\n if (includePatterns.length === 0) {\n return null;\n }\n\n // Rejects absolute paths or relative paths to parents.\n for (const pattern of includePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n if (pattern.endsWith(\"*\")) {\n endsWithWildcard = true;\n }\n }\n for (const pattern of excludePatterns) {\n if (path.isAbsolute(pattern) || pattern.includes(\"..\")) {\n throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);\n }\n }\n\n const includes = toMatcher(includePatterns);\n const excludes = toMatcher(excludePatterns);\n\n return new OverrideTester(\n [{ includes, excludes }],\n basePath,\n endsWithWildcard\n );\n }\n\n /**\n * Combine two testers by logical and.\n * If either of the testers was `null`, returns the other tester.\n * The `basePath` property of the two must be the same value.\n * @param {OverrideTester|null} a A tester.\n * @param {OverrideTester|null} b Another tester.\n * @returns {OverrideTester|null} Combined tester.\n */\n static and(a, b) {\n if (!b) {\n return a && new OverrideTester(\n a.patterns,\n a.basePath,\n a.endsWithWildcard\n );\n }\n if (!a) {\n return new OverrideTester(\n b.patterns,\n b.basePath,\n b.endsWithWildcard\n );\n }\n\n assert.strictEqual(a.basePath, b.basePath);\n return new OverrideTester(\n a.patterns.concat(b.patterns),\n a.basePath,\n a.endsWithWildcard || b.endsWithWildcard\n );\n }\n\n /**\n * Initialize this instance.\n * @param {Pattern[]} patterns The matchers.\n * @param {string} basePath The base path.\n * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.\n */\n constructor(patterns, basePath, endsWithWildcard = false) {\n\n /** @type {Pattern[]} */\n this.patterns = patterns;\n\n /** @type {string} */\n this.basePath = basePath;\n\n /** @type {boolean} */\n this.endsWithWildcard = endsWithWildcard;\n }\n\n /**\n * Test if a given path is matched or not.\n * @param {string} filePath The absolute path to the target file.\n * @returns {boolean} `true` if the path was matched.\n */\n test(filePath) {\n if (typeof filePath !== \"string\" || !path.isAbsolute(filePath)) {\n throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);\n }\n const relativePath = path.relative(this.basePath, filePath);\n\n return this.patterns.every(({ includes, excludes }) => (\n (!includes || includes.some(m => m.match(relativePath))) &&\n (!excludes || !excludes.some(m => m.match(relativePath)))\n ));\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} a JSON compatible object.\n */\n toJSON() {\n if (this.patterns.length === 1) {\n return {\n ...patternToJson(this.patterns[0]),\n basePath: this.basePath\n };\n }\n return {\n AND: this.patterns.map(patternToJson),\n basePath: this.basePath\n };\n }\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @returns {Object} an object to display by `console.log()`.\n */\n [util.inspect.custom]() {\n return this.toJSON();\n }\n}\n\nexport { OverrideTester };\n","/**\n * @fileoverview `ConfigArray` class.\n * @author Toru Nagashima \n */\n\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array.js\";\nimport { ConfigDependency } from \"./config-dependency.js\";\nimport { ExtractedConfig } from \"./extracted-config.js\";\nimport { IgnorePattern } from \"./ignore-pattern.js\";\nimport { OverrideTester } from \"./override-tester.js\";\n\nexport {\n ConfigArray,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs\n};\n","/**\n * @fileoverview Config file operations. This file must be usable in the browser,\n * so no Node-specific code can be here.\n * @author Nicholas C. Zakas\n */\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\nconst RULE_SEVERITY_STRINGS = [\"off\", \"warn\", \"error\"],\n RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {\n map[value] = index;\n return map;\n }, {}),\n VALID_SEVERITIES = [0, 1, 2, \"off\", \"warn\", \"error\"];\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * Normalizes the severity value of a rule's configuration to a number\n * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally\n * received from the user. A valid config value is either 0, 1, 2, the string \"off\" (treated the same as 0),\n * the string \"warn\" (treated the same as 1), the string \"error\" (treated the same as 2), or an array\n * whose first element is one of the above values. Strings are matched case-insensitively.\n * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.\n */\nfunction getRuleSeverity(ruleConfig) {\n const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (severityValue === 0 || severityValue === 1 || severityValue === 2) {\n return severityValue;\n }\n\n if (typeof severityValue === \"string\") {\n return RULE_SEVERITY[severityValue.toLowerCase()] || 0;\n }\n\n return 0;\n}\n\n/**\n * Converts old-style severity settings (0, 1, 2) into new-style\n * severity settings (off, warn, error) for all rules. Assumption is that severity\n * values have already been validated as correct.\n * @param {Object} config The config object to normalize.\n * @returns {void}\n */\nfunction normalizeToStrings(config) {\n\n if (config.rules) {\n Object.keys(config.rules).forEach(ruleId => {\n const ruleConfig = config.rules[ruleId];\n\n if (typeof ruleConfig === \"number\") {\n config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];\n } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === \"number\") {\n ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];\n }\n });\n }\n}\n\n/**\n * Determines if the severity for the given rule configuration represents an error.\n * @param {int|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} True if the rule represents an error, false if not.\n */\nfunction isErrorSeverity(ruleConfig) {\n return getRuleSeverity(ruleConfig) === 2;\n}\n\n/**\n * Checks whether a given config has valid severity or not.\n * @param {number|string|Array} ruleConfig The configuration for an individual rule.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isValidSeverity(ruleConfig) {\n let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;\n\n if (typeof severity === \"string\") {\n severity = severity.toLowerCase();\n }\n return VALID_SEVERITIES.indexOf(severity) !== -1;\n}\n\n/**\n * Checks whether every rule of a given config has valid severity or not.\n * @param {Object} config The configuration for rules.\n * @returns {boolean} `true` if the configuration has valid severity.\n */\nfunction isEverySeverityValid(config) {\n return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));\n}\n\n/**\n * Normalizes a value for a global in a config\n * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in\n * a global directive comment\n * @returns {(\"readable\"|\"writeable\"|\"off\")} The value normalized as a string\n * @throws Error if global value is invalid\n */\nfunction normalizeConfigGlobal(configuredValue) {\n switch (configuredValue) {\n case \"off\":\n return \"off\";\n\n case true:\n case \"true\":\n case \"writeable\":\n case \"writable\":\n return \"writable\";\n\n case null:\n case false:\n case \"false\":\n case \"readable\":\n case \"readonly\":\n return \"readonly\";\n\n default:\n throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);\n }\n}\n\nexport {\n getRuleSeverity,\n normalizeToStrings,\n isErrorSeverity,\n isValidSeverity,\n isEverySeverityValid,\n normalizeConfigGlobal\n};\n","/**\n * @fileoverview Provide the function that emits deprecation warnings.\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport path from \"path\";\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\n\n// Defitions for deprecation warnings.\nconst deprecationWarningMessages = {\n ESLINT_LEGACY_ECMAFEATURES:\n \"The 'ecmaFeatures' config file property is deprecated and has no effect.\",\n ESLINT_PERSONAL_CONFIG_LOAD:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please use a config file per project or the '--config' option.\",\n ESLINT_PERSONAL_CONFIG_SUPPRESS:\n \"'~/.eslintrc.*' config files have been deprecated. \" +\n \"Please remove it or add 'root:true' to the config files in your \" +\n \"projects in order to avoid loading '~/.eslintrc.*' accidentally.\"\n};\n\nconst sourceFileErrorCache = new Set();\n\n/**\n * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted\n * for each unique file path, but repeated invocations with the same file path have no effect.\n * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.\n * @param {string} source The name of the configuration source to report the warning for.\n * @param {string} errorCode The warning message to show.\n * @returns {void}\n */\nfunction emitDeprecationWarning(source, errorCode) {\n const cacheKey = JSON.stringify({ source, errorCode });\n\n if (sourceFileErrorCache.has(cacheKey)) {\n return;\n }\n sourceFileErrorCache.add(cacheKey);\n\n const rel = path.relative(process.cwd(), source);\n const message = deprecationWarningMessages[errorCode];\n\n process.emitWarning(\n `${message} (found in \"${rel}\")`,\n \"DeprecationWarning\",\n errorCode\n );\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n emitDeprecationWarning\n};\n","/**\n * @fileoverview The instance of Ajv validator.\n * @author Evgeny Poberezkin\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport Ajv from \"ajv\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/*\n * Copied from ajv/lib/refs/json-schema-draft-04.json\n * The MIT License (MIT)\n * Copyright (c) 2015-2017 Evgeny Poberezkin\n */\nconst metaSchema = {\n id: \"http://json-schema.org/draft-04/schema#\",\n $schema: \"http://json-schema.org/draft-04/schema#\",\n description: \"Core schema meta-schema\",\n definitions: {\n schemaArray: {\n type: \"array\",\n minItems: 1,\n items: { $ref: \"#\" }\n },\n positiveInteger: {\n type: \"integer\",\n minimum: 0\n },\n positiveIntegerDefault0: {\n allOf: [{ $ref: \"#/definitions/positiveInteger\" }, { default: 0 }]\n },\n simpleTypes: {\n enum: [\"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\"]\n },\n stringArray: {\n type: \"array\",\n items: { type: \"string\" },\n minItems: 1,\n uniqueItems: true\n }\n },\n type: \"object\",\n properties: {\n id: {\n type: \"string\"\n },\n $schema: {\n type: \"string\"\n },\n title: {\n type: \"string\"\n },\n description: {\n type: \"string\"\n },\n default: { },\n multipleOf: {\n type: \"number\",\n minimum: 0,\n exclusiveMinimum: true\n },\n maximum: {\n type: \"number\"\n },\n exclusiveMaximum: {\n type: \"boolean\",\n default: false\n },\n minimum: {\n type: \"number\"\n },\n exclusiveMinimum: {\n type: \"boolean\",\n default: false\n },\n maxLength: { $ref: \"#/definitions/positiveInteger\" },\n minLength: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n pattern: {\n type: \"string\",\n format: \"regex\"\n },\n additionalItems: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n items: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/schemaArray\" }\n ],\n default: { }\n },\n maxItems: { $ref: \"#/definitions/positiveInteger\" },\n minItems: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n uniqueItems: {\n type: \"boolean\",\n default: false\n },\n maxProperties: { $ref: \"#/definitions/positiveInteger\" },\n minProperties: { $ref: \"#/definitions/positiveIntegerDefault0\" },\n required: { $ref: \"#/definitions/stringArray\" },\n additionalProperties: {\n anyOf: [\n { type: \"boolean\" },\n { $ref: \"#\" }\n ],\n default: { }\n },\n definitions: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n properties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n patternProperties: {\n type: \"object\",\n additionalProperties: { $ref: \"#\" },\n default: { }\n },\n dependencies: {\n type: \"object\",\n additionalProperties: {\n anyOf: [\n { $ref: \"#\" },\n { $ref: \"#/definitions/stringArray\" }\n ]\n }\n },\n enum: {\n type: \"array\",\n minItems: 1,\n uniqueItems: true\n },\n type: {\n anyOf: [\n { $ref: \"#/definitions/simpleTypes\" },\n {\n type: \"array\",\n items: { $ref: \"#/definitions/simpleTypes\" },\n minItems: 1,\n uniqueItems: true\n }\n ]\n },\n format: { type: \"string\" },\n allOf: { $ref: \"#/definitions/schemaArray\" },\n anyOf: { $ref: \"#/definitions/schemaArray\" },\n oneOf: { $ref: \"#/definitions/schemaArray\" },\n not: { $ref: \"#\" }\n },\n dependencies: {\n exclusiveMaximum: [\"maximum\"],\n exclusiveMinimum: [\"minimum\"]\n },\n default: { }\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport default (additionalOptions = {}) => {\n const ajv = new Ajv({\n meta: false,\n useDefaults: true,\n validateSchema: false,\n missingRefs: \"ignore\",\n verbose: true,\n schemaId: \"auto\",\n ...additionalOptions\n });\n\n ajv.addMetaSchema(metaSchema);\n // eslint-disable-next-line no-underscore-dangle\n ajv._opts.defaultMeta = metaSchema.id;\n\n return ajv;\n};\n","/**\n * @fileoverview Defines a schema for configs.\n * @author Sylvan Mably\n */\n\nconst baseConfigProperties = {\n $schema: { type: \"string\" },\n env: { type: \"object\" },\n extends: { $ref: \"#/definitions/stringOrStrings\" },\n globals: { type: \"object\" },\n overrides: {\n type: \"array\",\n items: { $ref: \"#/definitions/overrideConfig\" },\n additionalItems: false\n },\n parser: { type: [\"string\", \"null\"] },\n parserOptions: { type: \"object\" },\n plugins: { type: \"array\" },\n processor: { type: \"string\" },\n rules: { type: \"object\" },\n settings: { type: \"object\" },\n noInlineConfig: { type: \"boolean\" },\n reportUnusedDisableDirectives: { type: \"boolean\" },\n\n ecmaFeatures: { type: \"object\" } // deprecated; logs a warning when used\n};\n\nconst configSchema = {\n definitions: {\n stringOrStrings: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false\n }\n ]\n },\n stringOrStringsRequired: {\n oneOf: [\n { type: \"string\" },\n {\n type: \"array\",\n items: { type: \"string\" },\n additionalItems: false,\n minItems: 1\n }\n ]\n },\n\n // Config at top-level.\n objectConfig: {\n type: \"object\",\n properties: {\n root: { type: \"boolean\" },\n ignorePatterns: { $ref: \"#/definitions/stringOrStrings\" },\n ...baseConfigProperties\n },\n additionalProperties: false\n },\n\n // Config in `overrides`.\n overrideConfig: {\n type: \"object\",\n properties: {\n excludedFiles: { $ref: \"#/definitions/stringOrStrings\" },\n files: { $ref: \"#/definitions/stringOrStringsRequired\" },\n ...baseConfigProperties\n },\n required: [\"files\"],\n additionalProperties: false\n }\n },\n\n $ref: \"#/definitions/objectConfig\"\n};\n\nexport default configSchema;\n","/**\n * @fileoverview Defines environment settings and globals.\n * @author Elan Shanker\n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport globals from \"globals\";\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n/**\n * Get the object that has difference.\n * @param {Record} current The newer object.\n * @param {Record} prev The older object.\n * @returns {Record} The difference object.\n */\nfunction getDiff(current, prev) {\n const retv = {};\n\n for (const [key, value] of Object.entries(current)) {\n if (!Object.hasOwnProperty.call(prev, key)) {\n retv[key] = value;\n }\n }\n\n return retv;\n}\n\nconst newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...\nconst newGlobals2017 = {\n Atomics: false,\n SharedArrayBuffer: false\n};\nconst newGlobals2020 = {\n BigInt: false,\n BigInt64Array: false,\n BigUint64Array: false,\n globalThis: false\n};\n\nconst newGlobals2021 = {\n AggregateError: false,\n FinalizationRegistry: false,\n WeakRef: false\n};\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/** @type {Map} */\nexport default new Map(Object.entries({\n\n // Language\n builtin: {\n globals: globals.es5\n },\n es6: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2015: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 6\n }\n },\n es2016: {\n globals: newGlobals2015,\n parserOptions: {\n ecmaVersion: 7\n }\n },\n es2017: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 8\n }\n },\n es2018: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 9\n }\n },\n es2019: {\n globals: { ...newGlobals2015, ...newGlobals2017 },\n parserOptions: {\n ecmaVersion: 10\n }\n },\n es2020: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },\n parserOptions: {\n ecmaVersion: 11\n }\n },\n es2021: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 12\n }\n },\n es2022: {\n globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },\n parserOptions: {\n ecmaVersion: 13\n }\n },\n\n // Platforms\n browser: {\n globals: globals.browser\n },\n node: {\n globals: globals.node,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n \"shared-node-browser\": {\n globals: globals[\"shared-node-browser\"]\n },\n worker: {\n globals: globals.worker\n },\n serviceworker: {\n globals: globals.serviceworker\n },\n\n // Frameworks\n commonjs: {\n globals: globals.commonjs,\n parserOptions: {\n ecmaFeatures: {\n globalReturn: true\n }\n }\n },\n amd: {\n globals: globals.amd\n },\n mocha: {\n globals: globals.mocha\n },\n jasmine: {\n globals: globals.jasmine\n },\n jest: {\n globals: globals.jest\n },\n phantomjs: {\n globals: globals.phantomjs\n },\n jquery: {\n globals: globals.jquery\n },\n qunit: {\n globals: globals.qunit\n },\n prototypejs: {\n globals: globals.prototypejs\n },\n shelljs: {\n globals: globals.shelljs\n },\n meteor: {\n globals: globals.meteor\n },\n mongo: {\n globals: globals.mongo\n },\n protractor: {\n globals: globals.protractor\n },\n applescript: {\n globals: globals.applescript\n },\n nashorn: {\n globals: globals.nashorn\n },\n atomtest: {\n globals: globals.atomtest\n },\n embertest: {\n globals: globals.embertest\n },\n webextensions: {\n globals: globals.webextensions\n },\n greasemonkey: {\n globals: globals.greasemonkey\n }\n}));\n","/**\n * @fileoverview Validates configs.\n * @author Brandon Mills\n */\n\n/* eslint class-methods-use-this: \"off\" */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport util from \"util\";\nimport * as ConfigOps from \"./config-ops.js\";\nimport { emitDeprecationWarning } from \"./deprecation-warnings.js\";\nimport ajvOrig from \"./ajv.js\";\nimport configSchema from \"../../conf/config-schema.js\";\nimport BuiltInEnvironments from \"../../conf/environments.js\";\n\nconst ajv = ajvOrig();\n\nconst ruleValidators = new WeakMap();\nconst noop = Function.prototype;\n\n//------------------------------------------------------------------------------\n// Private\n//------------------------------------------------------------------------------\nlet validateSchema;\nconst severityMap = {\n error: 2,\n warn: 1,\n off: 0\n};\n\nconst validated = new WeakSet();\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nexport default class ConfigValidator {\n constructor({ builtInRules = new Map() } = {}) {\n this.builtInRules = builtInRules;\n }\n\n /**\n * Gets a complete options schema for a rule.\n * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object\n * @returns {Object} JSON Schema for the rule's options.\n */\n getRuleOptionsSchema(rule) {\n if (!rule) {\n return null;\n }\n\n const schema = rule.schema || rule.meta && rule.meta.schema;\n\n // Given a tuple of schemas, insert warning level at the beginning\n if (Array.isArray(schema)) {\n if (schema.length) {\n return {\n type: \"array\",\n items: schema,\n minItems: 0,\n maxItems: schema.length\n };\n }\n return {\n type: \"array\",\n minItems: 0,\n maxItems: 0\n };\n\n }\n\n // Given a full schema, leave it alone\n return schema || null;\n }\n\n /**\n * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.\n * @param {options} options The given options for the rule.\n * @returns {number|string} The rule's severity value\n */\n validateRuleSeverity(options) {\n const severity = Array.isArray(options) ? options[0] : options;\n const normSeverity = typeof severity === \"string\" ? severityMap[severity.toLowerCase()] : severity;\n\n if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {\n return normSeverity;\n }\n\n throw new Error(`\\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util.inspect(severity).replace(/'/gu, \"\\\"\").replace(/\\n/gu, \"\")}').\\n`);\n\n }\n\n /**\n * Validates the non-severity options passed to a rule, based on its schema.\n * @param {{create: Function}} rule The rule to validate\n * @param {Array} localOptions The options for the rule, excluding severity\n * @returns {void}\n */\n validateRuleSchema(rule, localOptions) {\n if (!ruleValidators.has(rule)) {\n const schema = this.getRuleOptionsSchema(rule);\n\n if (schema) {\n ruleValidators.set(rule, ajv.compile(schema));\n }\n }\n\n const validateRule = ruleValidators.get(rule);\n\n if (validateRule) {\n validateRule(localOptions);\n if (validateRule.errors) {\n throw new Error(validateRule.errors.map(\n error => `\\tValue ${JSON.stringify(error.data)} ${error.message}.\\n`\n ).join(\"\"));\n }\n }\n }\n\n /**\n * Validates a rule's options against its schema.\n * @param {{create: Function}|null} rule The rule that the config is being validated for\n * @param {string} ruleId The rule's unique name.\n * @param {Array|number} options The given options for the rule.\n * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,\n * no source is prepended to the message.\n * @returns {void}\n */\n validateRuleOptions(rule, ruleId, options, source = null) {\n try {\n const severity = this.validateRuleSeverity(options);\n\n if (severity !== 0) {\n this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);\n }\n } catch (err) {\n const enhancedMessage = `Configuration for rule \"${ruleId}\" is invalid:\\n${err.message}`;\n\n if (typeof source === \"string\") {\n throw new Error(`${source}:\\n\\t${enhancedMessage}`);\n } else {\n throw new Error(enhancedMessage);\n }\n }\n }\n\n /**\n * Validates an environment object\n * @param {Object} environment The environment config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.\n * @returns {void}\n */\n validateEnvironment(\n environment,\n source,\n getAdditionalEnv = noop\n ) {\n\n // not having an environment is ok\n if (!environment) {\n return;\n }\n\n Object.keys(environment).forEach(id => {\n const env = getAdditionalEnv(id) || BuiltInEnvironments.get(id) || null;\n\n if (!env) {\n const message = `${source}:\\n\\tEnvironment key \"${id}\" is unknown\\n`;\n\n throw new Error(message);\n }\n });\n }\n\n /**\n * Validates a rules config object\n * @param {Object} rulesConfig The rules config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules\n * @returns {void}\n */\n validateRules(\n rulesConfig,\n source,\n getAdditionalRule = noop\n ) {\n if (!rulesConfig) {\n return;\n }\n\n Object.keys(rulesConfig).forEach(id => {\n const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;\n\n this.validateRuleOptions(rule, id, rulesConfig[id], source);\n });\n }\n\n /**\n * Validates a `globals` section of a config file\n * @param {Object} globalsConfig The `globals` section\n * @param {string|null} source The name of the configuration source to report in the event of an error.\n * @returns {void}\n */\n validateGlobals(globalsConfig, source = null) {\n if (!globalsConfig) {\n return;\n }\n\n Object.entries(globalsConfig)\n .forEach(([configuredGlobal, configuredValue]) => {\n try {\n ConfigOps.normalizeConfigGlobal(configuredValue);\n } catch (err) {\n throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\\n${err.message}`);\n }\n });\n }\n\n /**\n * Validate `processor` configuration.\n * @param {string|undefined} processorName The processor name.\n * @param {string} source The name of config file.\n * @param {function(id:string): Processor} getProcessor The getter of defined processors.\n * @returns {void}\n */\n validateProcessor(processorName, source, getProcessor) {\n if (processorName && !getProcessor(processorName)) {\n throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);\n }\n }\n\n /**\n * Formats an array of schema validation errors.\n * @param {Array} errors An array of error messages to format.\n * @returns {string} Formatted error message\n */\n formatErrors(errors) {\n return errors.map(error => {\n if (error.keyword === \"additionalProperties\") {\n const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;\n\n return `Unexpected top-level property \"${formattedPropertyPath}\"`;\n }\n if (error.keyword === \"type\") {\n const formattedField = error.dataPath.slice(1);\n const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join(\"/\") : error.schema;\n const formattedValue = JSON.stringify(error.data);\n\n return `Property \"${formattedField}\" is the wrong type (expected ${formattedExpectedType} but got \\`${formattedValue}\\`)`;\n }\n\n const field = error.dataPath[0] === \".\" ? error.dataPath.slice(1) : error.dataPath;\n\n return `\"${field}\" ${error.message}. Value: ${JSON.stringify(error.data)}`;\n }).map(message => `\\t- ${message}.\\n`).join(\"\");\n }\n\n /**\n * Validates the top level properties of the config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @returns {void}\n */\n validateConfigSchema(config, source = null) {\n validateSchema = validateSchema || ajv.compile(configSchema);\n\n if (!validateSchema(config)) {\n throw new Error(`ESLint configuration in ${source} is invalid:\\n${this.formatErrors(validateSchema.errors)}`);\n }\n\n if (Object.hasOwnProperty.call(config, \"ecmaFeatures\")) {\n emitDeprecationWarning(source, \"ESLINT_LEGACY_ECMAFEATURES\");\n }\n }\n\n /**\n * Validates an entire config object.\n * @param {Object} config The config object to validate.\n * @param {string} source The name of the configuration source to report in any errors.\n * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.\n * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.\n * @returns {void}\n */\n validate(config, source, getAdditionalRule, getAdditionalEnv) {\n this.validateConfigSchema(config, source);\n this.validateRules(config.rules, source, getAdditionalRule);\n this.validateEnvironment(config.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n\n for (const override of config.overrides || []) {\n this.validateRules(override.rules, source, getAdditionalRule);\n this.validateEnvironment(override.env, source, getAdditionalEnv);\n this.validateGlobals(config.globals, source);\n }\n }\n\n /**\n * Validate config array object.\n * @param {ConfigArray} configArray The config array to validate.\n * @returns {void}\n */\n validateConfigArray(configArray) {\n const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);\n const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);\n const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);\n\n // Validate.\n for (const element of configArray) {\n if (validated.has(element)) {\n continue;\n }\n validated.add(element);\n\n this.validateEnvironment(element.env, element.name, getPluginEnv);\n this.validateGlobals(element.globals, element.name);\n this.validateProcessor(element.processor, element.name, getPluginProcessor);\n this.validateRules(element.rules, element.name, getPluginRule);\n }\n }\n\n}\n","/**\n * @fileoverview Common helpers for naming of plugins, formatters and configs\n */\n\nconst NAMESPACE_REGEX = /^@.*\\//iu;\n\n/**\n * Brings package name to correct format based on prefix\n * @param {string} name The name of the package.\n * @param {string} prefix Can be either \"eslint-plugin\", \"eslint-config\" or \"eslint-formatter\"\n * @returns {string} Normalized name of the package\n * @private\n */\nfunction normalizePackageName(name, prefix) {\n let normalizedName = name;\n\n /**\n * On Windows, name can come in with Windows slashes instead of Unix slashes.\n * Normalize to Unix first to avoid errors later on.\n * https://github.com/eslint/eslint/issues/5644\n */\n if (normalizedName.includes(\"\\\\\")) {\n normalizedName = normalizedName.replace(/\\\\/gu, \"/\");\n }\n\n if (normalizedName.charAt(0) === \"@\") {\n\n /**\n * it's a scoped package\n * package name is the prefix, or just a username\n */\n const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, \"u\"),\n scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, \"u\");\n\n if (scopedPackageShortcutRegex.test(normalizedName)) {\n normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);\n } else if (!scopedPackageNameRegex.test(normalizedName.split(\"/\")[1])) {\n\n /**\n * for scoped packages, insert the prefix after the first / unless\n * the path is already @scope/eslint or @scope/eslint-xxx-yyy\n */\n normalizedName = normalizedName.replace(/^@([^/]+)\\/(.*)$/u, `@$1/${prefix}-$2`);\n }\n } else if (!normalizedName.startsWith(`${prefix}-`)) {\n normalizedName = `${prefix}-${normalizedName}`;\n }\n\n return normalizedName;\n}\n\n/**\n * Removes the prefix from a fullname.\n * @param {string} fullname The term which may have the prefix.\n * @param {string} prefix The prefix to remove.\n * @returns {string} The term without prefix.\n */\nfunction getShorthandName(fullname, prefix) {\n if (fullname[0] === \"@\") {\n let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, \"u\").exec(fullname);\n\n if (matchResult) {\n return matchResult[1];\n }\n\n matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, \"u\").exec(fullname);\n if (matchResult) {\n return `${matchResult[1]}/${matchResult[2]}`;\n }\n } else if (fullname.startsWith(`${prefix}-`)) {\n return fullname.slice(prefix.length + 1);\n }\n\n return fullname;\n}\n\n/**\n * Gets the scope (namespace) of a term.\n * @param {string} term The term which may have the namespace.\n * @returns {string} The namespace of the term if it has one.\n */\nfunction getNamespaceFromTerm(term) {\n const match = term.match(NAMESPACE_REGEX);\n\n return match ? match[0] : \"\";\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport {\n normalizePackageName,\n getShorthandName,\n getNamespaceFromTerm\n};\n","/**\n * Utility for resolving a module relative to another module\n * @author Teddy Katz\n */\n\nimport Module from \"module\";\n\n/*\n * `Module.createRequire` is added in v12.2.0. It supports URL as well.\n * We only support the case where the argument is a filepath, not a URL.\n */\nconst createRequire = Module.createRequire;\n\n/**\n * Resolves a Node module relative to another module\n * @param {string} moduleName The name of a Node module, or a path to a Node module.\n * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be\n * a file rather than a directory, but the file need not actually exist.\n * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`\n */\nfunction resolve(moduleName, relativeToPath) {\n try {\n return createRequire(relativeToPath).resolve(moduleName);\n } catch (error) {\n\n // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.\n if (\n typeof error === \"object\" &&\n error !== null &&\n error.code === \"MODULE_NOT_FOUND\" &&\n !error.requireStack &&\n error.message.includes(moduleName)\n ) {\n error.message += `\\nRequire stack:\\n- ${relativeToPath}`;\n }\n throw error;\n }\n}\n\nexport {\n resolve\n};\n","/**\n * @fileoverview The factory of `ConfigArray` objects.\n *\n * This class provides methods to create `ConfigArray` instance.\n *\n * - `create(configData, options)`\n * Create a `ConfigArray` instance from a config data. This is to handle CLI\n * options except `--config`.\n * - `loadFile(filePath, options)`\n * Create a `ConfigArray` instance from a config file. This is to handle\n * `--config` option. If the file was not found, throws the following error:\n * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.\n * - If the filename was `package.json`, an IO error or an\n * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.\n * - Otherwise, an IO error such as `ENOENT`.\n * - `loadInDirectory(directoryPath, options)`\n * Create a `ConfigArray` instance from a config file which is on a given\n * directory. This tries to load `.eslintrc.*` or `package.json`. If not\n * found, returns an empty `ConfigArray`.\n * - `loadESLintIgnore(filePath)`\n * Create a `ConfigArray` instance from a config file that is `.eslintignore`\n * format. This is to handle `--ignore-path` option.\n * - `loadDefaultESLintIgnore()`\n * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in\n * the current working directory.\n *\n * `ConfigArrayFactory` class has the responsibility that loads configuration\n * files, including loading `extends`, `parser`, and `plugins`. The created\n * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.\n *\n * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class\n * handles cascading and hierarchy.\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport fs from \"fs\";\nimport { createRequire } from \"module\";\nimport path from \"path\";\nimport stripComments from \"strip-json-comments\";\n\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern,\n OverrideTester\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\n\nconst require = createRequire(import.meta.url);\n\nconst debug = debugOrig(\"eslintrc:config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\nconst configFilenames = [\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \".eslintrc.json\",\n \".eslintrc\",\n \"package.json\"\n];\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").OverrideConfigData} OverrideConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {import(\"./config-array/config-dependency\").DependentParser} DependentParser */\n/** @typedef {import(\"./config-array/config-dependency\").DependentPlugin} DependentPlugin */\n/** @typedef {ConfigArray[0]} ConfigArrayElement */\n\n/**\n * @typedef {Object} ConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {string} [cwd] The path to the current working directory.\n * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryInternalSlots\n * @property {Map} additionalPluginPool The map for additional plugins.\n * @property {string} cwd The path to the current working directory.\n * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {string} pluginBasePath The base path to resolve plugins.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/**\n * @typedef {Object} ConfigArrayFactoryLoadingContext\n * @property {string} filePath The path to the current configuration.\n * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @property {string} name The name of the current configuration.\n * @property {\"config\" | \"ignore\" | \"implicit-processor\"} type The type of the current configuration. This is `\"config\"` in normal. This is `\"ignore\"` if it came from `.eslintignore`. This is `\"implicit-processor\"` if it came from legacy file-extension processors.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/** @type {WeakMap} */\nconst normalizedPlugins = new WeakMap();\n\n/**\n * Check if a given string is a file path.\n * @param {string} nameOrPath A module name or file path.\n * @returns {boolean} `true` if the `nameOrPath` is a file path.\n */\nfunction isFilePath(nameOrPath) {\n return (\n /^\\.{1,2}[/\\\\]/u.test(nameOrPath) ||\n path.isAbsolute(nameOrPath)\n );\n}\n\n/**\n * Convenience wrapper for synchronously reading file contents.\n * @param {string} filePath The filename to read.\n * @returns {string} The file contents, with the BOM removed.\n * @private\n */\nfunction readFile(filePath) {\n return fs.readFileSync(filePath, \"utf8\").replace(/^\\ufeff/u, \"\");\n}\n\n/**\n * Loads a YAML configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadYAMLConfigFile(filePath) {\n debug(`Loading YAML config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n\n // empty YAML file can be null, so always use\n return yaml.load(readFile(filePath)) || {};\n } catch (e) {\n debug(`Error reading YAML file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JSON configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSONConfigFile(filePath) {\n debug(`Loading JSON config file: ${filePath}`);\n\n try {\n return JSON.parse(stripComments(readFile(filePath)));\n } catch (e) {\n debug(`Error reading JSON file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n e.messageTemplate = \"failed-to-read-json\";\n e.messageData = {\n path: filePath,\n message: e.message\n };\n throw e;\n }\n}\n\n/**\n * Loads a legacy (.eslintrc) configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadLegacyConfigFile(filePath) {\n debug(`Loading legacy config file: ${filePath}`);\n\n // lazy load YAML to improve performance when not used\n const yaml = require(\"js-yaml\");\n\n try {\n return yaml.load(stripComments(readFile(filePath))) || /* istanbul ignore next */ {};\n } catch (e) {\n debug(\"Error reading YAML file: %s\\n%o\", filePath, e);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a JavaScript configuration from a file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadJSConfigFile(filePath) {\n debug(`Loading JS config file: ${filePath}`);\n try {\n return require(filePath);\n } catch (e) {\n debug(`Error reading JavaScript file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a configuration from a package.json file.\n * @param {string} filePath The filename to load.\n * @returns {ConfigData} The configuration object from the file.\n * @throws {Error} If the file cannot be read.\n * @private\n */\nfunction loadPackageJSONConfigFile(filePath) {\n debug(`Loading package.json config file: ${filePath}`);\n try {\n const packageData = loadJSONConfigFile(filePath);\n\n if (!Object.hasOwnProperty.call(packageData, \"eslintConfig\")) {\n throw Object.assign(\n new Error(\"package.json file doesn't have 'eslintConfig' field.\"),\n { code: \"ESLINT_CONFIG_FIELD_NOT_FOUND\" }\n );\n }\n\n return packageData.eslintConfig;\n } catch (e) {\n debug(`Error reading package.json file: ${filePath}`);\n e.message = `Cannot read config file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Loads a `.eslintignore` from a file.\n * @param {string} filePath The filename to load.\n * @returns {string[]} The ignore patterns from the file.\n * @private\n */\nfunction loadESLintIgnoreFile(filePath) {\n debug(`Loading .eslintignore file: ${filePath}`);\n\n try {\n return readFile(filePath)\n .split(/\\r?\\n/gu)\n .filter(line => line.trim() !== \"\" && !line.startsWith(\"#\"));\n } catch (e) {\n debug(`Error reading .eslintignore file: ${filePath}`);\n e.message = `Cannot read .eslintignore file: ${filePath}\\nError: ${e.message}`;\n throw e;\n }\n}\n\n/**\n * Creates an error to notify about a missing config to extend from.\n * @param {string} configName The name of the missing config.\n * @param {string} importerName The name of the config that imported the missing config\n * @param {string} messageTemplate The text template to source error strings from.\n * @returns {Error} The error object to throw\n * @private\n */\nfunction configInvalidError(configName, importerName, messageTemplate) {\n return Object.assign(\n new Error(`Failed to load config \"${configName}\" to extend from.`),\n {\n messageTemplate,\n messageData: { configName, importerName }\n }\n );\n}\n\n/**\n * Loads a configuration file regardless of the source. Inspects the file path\n * to determine the correctly way to load the config file.\n * @param {string} filePath The path to the configuration.\n * @returns {ConfigData|null} The configuration information.\n * @private\n */\nfunction loadConfigFile(filePath) {\n switch (path.extname(filePath)) {\n case \".js\":\n case \".cjs\":\n return loadJSConfigFile(filePath);\n\n case \".json\":\n if (path.basename(filePath) === \"package.json\") {\n return loadPackageJSONConfigFile(filePath);\n }\n return loadJSONConfigFile(filePath);\n\n case \".yaml\":\n case \".yml\":\n return loadYAMLConfigFile(filePath);\n\n default:\n return loadLegacyConfigFile(filePath);\n }\n}\n\n/**\n * Write debug log.\n * @param {string} request The requested module name.\n * @param {string} relativeTo The file path to resolve the request relative to.\n * @param {string} filePath The resolved file path.\n * @returns {void}\n */\nfunction writeDebugLogForLoading(request, relativeTo, filePath) {\n /* istanbul ignore next */\n if (debug.enabled) {\n let nameAndVersion = null;\n\n try {\n const packageJsonPath = ModuleResolver.resolve(\n `${request}/package.json`,\n relativeTo\n );\n const { version = \"unknown\" } = require(packageJsonPath);\n\n nameAndVersion = `${request}@${version}`;\n } catch (error) {\n debug(\"package.json was not found:\", error.message);\n nameAndVersion = request;\n }\n\n debug(\"Loaded: %s (%s)\", nameAndVersion, filePath);\n }\n}\n\n/**\n * Create a new context with default values.\n * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.\n * @param {\"config\" | \"ignore\" | \"implicit-processor\" | undefined} providedType The type of the current configuration. Default is `\"config\"`.\n * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.\n * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.\n * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.\n * @returns {ConfigArrayFactoryLoadingContext} The created context.\n */\nfunction createContext(\n { cwd, resolvePluginsRelativeTo },\n providedType,\n providedName,\n providedFilePath,\n providedMatchBasePath\n) {\n const filePath = providedFilePath\n ? path.resolve(cwd, providedFilePath)\n : \"\";\n const matchBasePath =\n (providedMatchBasePath && path.resolve(cwd, providedMatchBasePath)) ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const name =\n providedName ||\n (filePath && path.relative(cwd, filePath)) ||\n \"\";\n const pluginBasePath =\n resolvePluginsRelativeTo ||\n (filePath && path.dirname(filePath)) ||\n cwd;\n const type = providedType || \"config\";\n\n return { filePath, matchBasePath, name, pluginBasePath, type };\n}\n\n/**\n * Normalize a given plugin.\n * - Ensure the object to have four properties: configs, environments, processors, and rules.\n * - Ensure the object to not have other properties.\n * @param {Plugin} plugin The plugin to normalize.\n * @returns {Plugin} The normalized plugin.\n */\nfunction normalizePlugin(plugin) {\n\n // first check the cache\n let normalizedPlugin = normalizedPlugins.get(plugin);\n\n if (normalizedPlugin) {\n return normalizedPlugin;\n }\n\n normalizedPlugin = {\n configs: plugin.configs || {},\n environments: plugin.environments || {},\n processors: plugin.processors || {},\n rules: plugin.rules || {}\n };\n\n // save the reference for later\n normalizedPlugins.set(plugin, normalizedPlugin);\n\n return normalizedPlugin;\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\n/**\n * The factory of `ConfigArray` objects.\n */\nclass ConfigArrayFactory {\n\n /**\n * Initialize this instance.\n * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.\n */\n constructor({\n additionalPluginPool = new Map(),\n cwd = process.cwd(),\n resolvePluginsRelativeTo,\n builtInRules,\n resolver = ModuleResolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = {}) {\n internalSlotsMap.set(this, {\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo:\n resolvePluginsRelativeTo &&\n path.resolve(cwd, resolvePluginsRelativeTo),\n builtInRules,\n resolver,\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n });\n }\n\n /**\n * Create `ConfigArray` instance from a config data.\n * @param {ConfigData|null} configData The config data to create.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.filePath] The path to this config data.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n create(configData, { basePath, filePath, name } = {}) {\n if (!configData) {\n return new ConfigArray();\n }\n\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n const elements = this._normalizeConfigData(configData, ctx);\n\n return new ConfigArray(...elements);\n }\n\n /**\n * Load a config file.\n * @param {string} filePath The path to a config file.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config.\n */\n loadFile(filePath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(slots, \"config\", name, filePath, basePath);\n\n return new ConfigArray(...this._loadConfigData(ctx));\n }\n\n /**\n * Load the config file on a given directory if exists.\n * @param {string} directoryPath The path to a directory.\n * @param {Object} [options] The options.\n * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.\n * @param {string} [options.name] The config name.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadInDirectory(directoryPath, { basePath, name } = {}) {\n const slots = internalSlotsMap.get(this);\n\n for (const filename of configFilenames) {\n const ctx = createContext(\n slots,\n \"config\",\n name,\n path.join(directoryPath, filename),\n basePath\n );\n\n if (fs.existsSync(ctx.filePath) && fs.statSync(ctx.filePath).isFile()) {\n let configData;\n\n try {\n configData = loadConfigFile(ctx.filePath);\n } catch (error) {\n if (!error || error.code !== \"ESLINT_CONFIG_FIELD_NOT_FOUND\") {\n throw error;\n }\n }\n\n if (configData) {\n debug(`Config file found: ${ctx.filePath}`);\n return new ConfigArray(\n ...this._normalizeConfigData(configData, ctx)\n );\n }\n }\n }\n\n debug(`Config file not found on ${directoryPath}`);\n return new ConfigArray();\n }\n\n /**\n * Check if a config file on a given directory exists or not.\n * @param {string} directoryPath The path to a directory.\n * @returns {string | null} The path to the found config file. If not found then null.\n */\n static getPathToConfigFileInDirectory(directoryPath) {\n for (const filename of configFilenames) {\n const filePath = path.join(directoryPath, filename);\n\n if (fs.existsSync(filePath)) {\n if (filename === \"package.json\") {\n try {\n loadPackageJSONConfigFile(filePath);\n return filePath;\n } catch { /* ignore */ }\n } else {\n return filePath;\n }\n }\n }\n return null;\n }\n\n /**\n * Load `.eslintignore` file.\n * @param {string} filePath The path to a `.eslintignore` file to load.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadESLintIgnore(filePath) {\n const slots = internalSlotsMap.get(this);\n const ctx = createContext(\n slots,\n \"ignore\",\n void 0,\n filePath,\n slots.cwd\n );\n const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)\n );\n }\n\n /**\n * Load `.eslintignore` file in the current working directory.\n * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.\n */\n loadDefaultESLintIgnore() {\n const slots = internalSlotsMap.get(this);\n const eslintIgnorePath = path.resolve(slots.cwd, \".eslintignore\");\n const packageJsonPath = path.resolve(slots.cwd, \"package.json\");\n\n if (fs.existsSync(eslintIgnorePath)) {\n return this.loadESLintIgnore(eslintIgnorePath);\n }\n if (fs.existsSync(packageJsonPath)) {\n const data = loadJSONConfigFile(packageJsonPath);\n\n if (Object.hasOwnProperty.call(data, \"eslintIgnore\")) {\n if (!Array.isArray(data.eslintIgnore)) {\n throw new Error(\"Package.json eslintIgnore property requires an array of paths\");\n }\n const ctx = createContext(\n slots,\n \"ignore\",\n \"eslintIgnore in package.json\",\n packageJsonPath,\n slots.cwd\n );\n\n return new ConfigArray(\n ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)\n );\n }\n }\n\n return new ConfigArray();\n }\n\n /**\n * Load a given config file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} Loaded config.\n * @private\n */\n _loadConfigData(ctx) {\n return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);\n }\n\n /**\n * Normalize a given `.eslintignore` data to config array elements.\n * @param {string[]} ignorePatterns The patterns to ignore files.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeESLintIgnoreData(ignorePatterns, ctx) {\n const elements = this._normalizeObjectConfigData(\n { ignorePatterns },\n ctx\n );\n\n // Set `ignorePattern.loose` flag for backward compatibility.\n for (const element of elements) {\n if (element.ignorePattern) {\n element.ignorePattern.loose = true;\n }\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _normalizeConfigData(configData, ctx) {\n const validator = new ConfigValidator();\n\n validator.validateConfigSchema(configData, ctx.name || ctx.filePath);\n return this._normalizeObjectConfigData(configData, ctx);\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData|OverrideConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigData(configData, ctx) {\n const { files, excludedFiles, ...configBody } = configData;\n const criteria = OverrideTester.create(\n files,\n excludedFiles,\n ctx.matchBasePath\n );\n const elements = this._normalizeObjectConfigDataBody(configBody, ctx);\n\n // Apply the criteria to every element.\n for (const element of elements) {\n\n /*\n * Merge the criteria.\n * This is for the `overrides` entries that came from the\n * configurations of `overrides[].extends`.\n */\n element.criteria = OverrideTester.and(criteria, element.criteria);\n\n /*\n * Remove `root` property to ignore `root` settings which came from\n * `extends` in `overrides`.\n */\n if (element.criteria) {\n element.root = void 0;\n }\n\n yield element;\n }\n }\n\n /**\n * Normalize a given config to an array.\n * @param {ConfigData} configData The config data to normalize.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n *_normalizeObjectConfigDataBody(\n {\n env,\n extends: extend,\n globals,\n ignorePatterns,\n noInlineConfig,\n parser: parserName,\n parserOptions,\n plugins: pluginList,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings,\n overrides: overrideList = []\n },\n ctx\n ) {\n const extendList = Array.isArray(extend) ? extend : [extend];\n const ignorePattern = ignorePatterns && new IgnorePattern(\n Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],\n ctx.matchBasePath\n );\n\n // Flatten `extends`.\n for (const extendName of extendList.filter(Boolean)) {\n yield* this._loadExtends(extendName, ctx);\n }\n\n // Load parser & plugins.\n const parser = parserName && this._loadParser(parserName, ctx);\n const plugins = pluginList && this._loadPlugins(pluginList, ctx);\n\n // Yield pseudo config data for file extension processors.\n if (plugins) {\n yield* this._takeFileExtensionProcessors(plugins, ctx);\n }\n\n // Yield the config data except `extends` and `overrides`.\n yield {\n\n // Debug information.\n type: ctx.type,\n name: ctx.name,\n filePath: ctx.filePath,\n\n // Config data.\n criteria: null,\n env,\n globals,\n ignorePattern,\n noInlineConfig,\n parser,\n parserOptions,\n plugins,\n processor,\n reportUnusedDisableDirectives,\n root,\n rules,\n settings\n };\n\n // Flatten `overries`.\n for (let i = 0; i < overrideList.length; ++i) {\n yield* this._normalizeObjectConfigData(\n overrideList[i],\n { ...ctx, name: `${ctx.name}#overrides[${i}]` }\n );\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtends(extendName, ctx) {\n debug(\"Loading {extends:%j} relative to %s\", extendName, ctx.filePath);\n try {\n if (extendName.startsWith(\"eslint:\")) {\n return this._loadExtendedBuiltInConfig(extendName, ctx);\n }\n if (extendName.startsWith(\"plugin:\")) {\n return this._loadExtendedPluginConfig(extendName, ctx);\n }\n return this._loadExtendedShareableConfig(extendName, ctx);\n } catch (error) {\n error.message += `\\nReferenced from: ${ctx.filePath || ctx.name}`;\n throw error;\n }\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedBuiltInConfig(extendName, ctx) {\n const {\n eslintAllPath,\n getEslintAllConfig,\n eslintRecommendedPath,\n getEslintRecommendedConfig\n } = internalSlotsMap.get(this);\n\n if (extendName === \"eslint:recommended\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintRecommendedConfig) {\n if (typeof getEslintRecommendedConfig !== \"function\") {\n throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);\n }\n return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintRecommendedPath\n });\n }\n if (extendName === \"eslint:all\") {\n const name = `${ctx.name} » ${extendName}`;\n\n if (getEslintAllConfig) {\n if (typeof getEslintAllConfig !== \"function\") {\n throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);\n }\n return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: \"\" });\n }\n return this._loadConfigData({\n ...ctx,\n name,\n filePath: eslintAllPath\n });\n }\n\n throw configInvalidError(extendName, ctx.name, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedPluginConfig(extendName, ctx) {\n const slashIndex = extendName.lastIndexOf(\"/\");\n\n if (slashIndex === -1) {\n throw configInvalidError(extendName, ctx.filePath, \"plugin-invalid\");\n }\n\n const pluginName = extendName.slice(\"plugin:\".length, slashIndex);\n const configName = extendName.slice(slashIndex + 1);\n\n if (isFilePath(pluginName)) {\n throw new Error(\"'extends' cannot use a file path for plugins.\");\n }\n\n const plugin = this._loadPlugin(pluginName, ctx);\n const configData =\n plugin.definition &&\n plugin.definition.configs[configName];\n\n if (configData) {\n return this._normalizeConfigData(configData, {\n ...ctx,\n filePath: plugin.filePath || ctx.filePath,\n name: `${ctx.name} » plugin:${plugin.id}/${configName}`\n });\n }\n\n throw plugin.error || configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n\n /**\n * Load configs of an element in `extends`.\n * @param {string} extendName The name of a base config.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The normalized config.\n * @private\n */\n _loadExtendedShareableConfig(extendName, ctx) {\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n let request;\n\n if (isFilePath(extendName)) {\n request = extendName;\n } else if (extendName.startsWith(\".\")) {\n request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.\n } else {\n request = naming.normalizePackageName(\n extendName,\n \"eslint-config\"\n );\n }\n\n let filePath;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (error) {\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n throw configInvalidError(extendName, ctx.filePath, \"extend-config-missing\");\n }\n throw error;\n }\n\n writeDebugLogForLoading(request, relativeTo, filePath);\n return this._loadConfigData({\n ...ctx,\n filePath,\n name: `${ctx.name} » ${request}`\n });\n }\n\n /**\n * Load given plugins.\n * @param {string[]} names The plugin names to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {Record} The loaded parser.\n * @private\n */\n _loadPlugins(names, ctx) {\n return names.reduce((map, name) => {\n if (isFilePath(name)) {\n throw new Error(\"Plugins array cannot includes file paths.\");\n }\n const plugin = this._loadPlugin(name, ctx);\n\n map[plugin.id] = plugin;\n\n return map;\n }, {});\n }\n\n /**\n * Load a given parser.\n * @param {string} nameOrPath The package name or the path to a parser file.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentParser} The loaded parser.\n */\n _loadParser(nameOrPath, ctx) {\n debug(\"Loading parser %j from %s\", nameOrPath, ctx.filePath);\n\n const { cwd, resolver } = internalSlotsMap.get(this);\n const relativeTo = ctx.filePath || path.join(cwd, \"__placeholder__.js\");\n\n try {\n const filePath = resolver.resolve(nameOrPath, relativeTo);\n\n writeDebugLogForLoading(nameOrPath, relativeTo, filePath);\n\n return new ConfigDependency({\n definition: require(filePath),\n filePath,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (error) {\n\n // If the parser name is \"espree\", load the espree of ESLint.\n if (nameOrPath === \"espree\") {\n debug(\"Fallback espree.\");\n return new ConfigDependency({\n definition: require(\"espree\"),\n filePath: require.resolve(\"espree\"),\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n debug(\"Failed to load parser '%s' declared in '%s'.\", nameOrPath, ctx.name);\n error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;\n\n return new ConfigDependency({\n error,\n id: nameOrPath,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n }\n\n /**\n * Load a given plugin.\n * @param {string} name The plugin name to load.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {DependentPlugin} The loaded plugin.\n * @private\n */\n _loadPlugin(name, ctx) {\n debug(\"Loading plugin %j from %s\", name, ctx.filePath);\n\n const { additionalPluginPool, resolver } = internalSlotsMap.get(this);\n const request = naming.normalizePackageName(name, \"eslint-plugin\");\n const id = naming.getShorthandName(request, \"eslint-plugin\");\n const relativeTo = path.join(ctx.pluginBasePath, \"__placeholder__.js\");\n\n if (name.match(/\\s+/u)) {\n const error = Object.assign(\n new Error(`Whitespace found in plugin name '${name}'`),\n {\n messageTemplate: \"whitespace-found\",\n messageData: { pluginName: request }\n }\n );\n\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n // Check for additional pool.\n const plugin =\n additionalPluginPool.get(request) ||\n additionalPluginPool.get(id);\n\n if (plugin) {\n return new ConfigDependency({\n definition: normalizePlugin(plugin),\n filePath: \"\", // It's unknown where the plugin came from.\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n let filePath;\n let error;\n\n try {\n filePath = resolver.resolve(request, relativeTo);\n } catch (resolveError) {\n error = resolveError;\n /* istanbul ignore else */\n if (error && error.code === \"MODULE_NOT_FOUND\") {\n error.messageTemplate = \"plugin-missing\";\n error.messageData = {\n pluginName: request,\n resolvePluginsRelativeTo: ctx.pluginBasePath,\n importerName: ctx.name\n };\n }\n }\n\n if (filePath) {\n try {\n writeDebugLogForLoading(request, relativeTo, filePath);\n\n const startTime = Date.now();\n const pluginDefinition = require(filePath);\n\n debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);\n\n return new ConfigDependency({\n definition: normalizePlugin(pluginDefinition),\n filePath,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n } catch (loadError) {\n error = loadError;\n }\n }\n\n debug(\"Failed to load plugin '%s' declared in '%s'.\", name, ctx.name);\n error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;\n return new ConfigDependency({\n error,\n id,\n importerName: ctx.name,\n importerPath: ctx.filePath\n });\n }\n\n /**\n * Take file expression processors as config array elements.\n * @param {Record} plugins The plugin definitions.\n * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.\n * @returns {IterableIterator} The config array elements of file expression processors.\n * @private\n */\n *_takeFileExtensionProcessors(plugins, ctx) {\n for (const pluginId of Object.keys(plugins)) {\n const processors =\n plugins[pluginId] &&\n plugins[pluginId].definition &&\n plugins[pluginId].definition.processors;\n\n if (!processors) {\n continue;\n }\n\n for (const processorId of Object.keys(processors)) {\n if (processorId.startsWith(\".\")) {\n yield* this._normalizeObjectConfigData(\n {\n files: [`*${processorId}`],\n processor: `${pluginId}/${processorId}`\n },\n {\n ...ctx,\n type: \"implicit-processor\",\n name: `${ctx.name}#processors[\"${pluginId}/${processorId}\"]`\n }\n );\n }\n }\n }\n }\n}\n\nexport { ConfigArrayFactory, createContext };\n","/**\n * @fileoverview `CascadingConfigArrayFactory` class.\n *\n * `CascadingConfigArrayFactory` class has a responsibility:\n *\n * 1. Handles cascading of config files.\n *\n * It provides two methods:\n *\n * - `getConfigArrayForFile(filePath)`\n * Get the corresponded configuration of a given file. This method doesn't\n * throw even if the given file didn't exist.\n * - `clearCache()`\n * Clear the internal cache. You have to call this method when\n * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends\n * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)\n *\n * @author Toru Nagashima \n */\n\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport debugOrig from \"debug\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\nimport {\n ConfigArray,\n ConfigDependency,\n IgnorePattern\n} from \"./config-array/index.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport { emitDeprecationWarning } from \"./shared/deprecation-warnings.js\";\n\nconst debug = debugOrig(\"eslintrc:cascading-config-array-factory\");\n\n//------------------------------------------------------------------------------\n// Helpers\n//------------------------------------------------------------------------------\n\n// Define types for VSCode IntelliSense.\n/** @typedef {import(\"./shared/types\").ConfigData} ConfigData */\n/** @typedef {import(\"./shared/types\").Parser} Parser */\n/** @typedef {import(\"./shared/types\").Plugin} Plugin */\n/** @typedef {import(\"./shared/types\").Rule} Rule */\n/** @typedef {ReturnType} ConfigArray */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryOptions\n * @property {Map} [additionalPluginPool] The map for additional plugins.\n * @property {ConfigData} [baseConfig] The config by `baseConfig` option.\n * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.\n * @property {string} [cwd] The base directory to start lookup.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]} [rulePaths] The value of `--rulesdir` option.\n * @property {string} [specificConfigPath] The value of `--config` option.\n * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/**\n * @typedef {Object} CascadingConfigArrayFactoryInternalSlots\n * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.\n * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.\n * @property {ConfigArray} cliConfigArray The config array of CLI options.\n * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.\n * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.\n * @property {Map} configCache The cache from directory paths to config arrays.\n * @property {string} cwd The base directory to start lookup.\n * @property {WeakMap} finalizeCache The cache from config arrays to finalized config arrays.\n * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.\n * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.\n * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.\n * @property {boolean} useEslintrc if `false` then it doesn't load config files.\n * @property {Function} loadRules The function to use to load rules.\n * @property {Map} builtInRules The rules that are built in to ESLint.\n * @property {Object} [resolver=ModuleResolver] The module resolver object.\n * @property {string} eslintAllPath The path to the definitions for eslint:all.\n * @property {Function} getEslintAllConfig Returns the config data for eslint:all.\n * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.\n * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.\n */\n\n/** @type {WeakMap} */\nconst internalSlotsMap = new WeakMap();\n\n/**\n * Create the config array from `baseConfig` and `rulePaths`.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createBaseConfigArray({\n configArrayFactory,\n baseConfigData,\n rulePaths,\n cwd,\n loadRules\n}) {\n const baseConfigArray = configArrayFactory.create(\n baseConfigData,\n { name: \"BaseConfig\" }\n );\n\n /*\n * Create the config array element for the default ignore patterns.\n * This element has `ignorePattern` property that ignores the default\n * patterns in the current working directory.\n */\n baseConfigArray.unshift(configArrayFactory.create(\n { ignorePatterns: IgnorePattern.DefaultPatterns },\n { name: \"DefaultIgnorePattern\" }\n )[0]);\n\n /*\n * Load rules `--rulesdir` option as a pseudo plugin.\n * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate\n * the rule's options with only information in the config array.\n */\n if (rulePaths && rulePaths.length > 0) {\n baseConfigArray.push({\n type: \"config\",\n name: \"--rulesdir\",\n filePath: \"\",\n plugins: {\n \"\": new ConfigDependency({\n definition: {\n rules: rulePaths.reduce(\n (map, rulesPath) => Object.assign(\n map,\n loadRules(rulesPath, cwd)\n ),\n {}\n )\n },\n filePath: \"\",\n id: \"\",\n importerName: \"--rulesdir\",\n importerPath: \"\"\n })\n }\n });\n }\n\n return baseConfigArray;\n}\n\n/**\n * Create the config array from CLI options.\n * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.\n * @returns {ConfigArray} The config array of the base configs.\n */\nfunction createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n}) {\n const cliConfigArray = configArrayFactory.create(\n cliConfigData,\n { name: \"CLIOptions\" }\n );\n\n cliConfigArray.unshift(\n ...(ignorePath\n ? configArrayFactory.loadESLintIgnore(ignorePath)\n : configArrayFactory.loadDefaultESLintIgnore())\n );\n\n if (specificConfigPath) {\n cliConfigArray.unshift(\n ...configArrayFactory.loadFile(\n specificConfigPath,\n { name: \"--config\", basePath: cwd }\n )\n );\n }\n\n return cliConfigArray;\n}\n\n/**\n * The error type when there are files matched by a glob, but all of them have been ignored.\n */\nclass ConfigurationNotFoundError extends Error {\n\n // eslint-disable-next-line jsdoc/require-description\n /**\n * @param {string} directoryPath The directory path.\n */\n constructor(directoryPath) {\n super(`No ESLint configuration found in ${directoryPath}.`);\n this.messageTemplate = \"no-config-found\";\n this.messageData = { directoryPath };\n }\n}\n\n/**\n * This class provides the functionality that enumerates every file which is\n * matched by given glob patterns and that configuration.\n */\nclass CascadingConfigArrayFactory {\n\n /**\n * Initialize this enumerator.\n * @param {CascadingConfigArrayFactoryOptions} options The options.\n */\n constructor({\n additionalPluginPool = new Map(),\n baseConfig: baseConfigData = null,\n cliConfig: cliConfigData = null,\n cwd = process.cwd(),\n ignorePath,\n resolvePluginsRelativeTo,\n rulePaths = [],\n specificConfigPath = null,\n useEslintrc = true,\n builtInRules = new Map(),\n loadRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n } = {}) {\n const configArrayFactory = new ConfigArrayFactory({\n additionalPluginPool,\n cwd,\n resolvePluginsRelativeTo,\n builtInRules,\n resolver,\n eslintRecommendedPath,\n getEslintRecommendedConfig,\n eslintAllPath,\n getEslintAllConfig\n });\n\n internalSlotsMap.set(this, {\n baseConfigArray: createBaseConfigArray({\n baseConfigData,\n configArrayFactory,\n cwd,\n rulePaths,\n loadRules\n }),\n baseConfigData,\n cliConfigArray: createCLIConfigArray({\n cliConfigData,\n configArrayFactory,\n cwd,\n ignorePath,\n specificConfigPath\n }),\n cliConfigData,\n configArrayFactory,\n configCache: new Map(),\n cwd,\n finalizeCache: new WeakMap(),\n ignorePath,\n rulePaths,\n specificConfigPath,\n useEslintrc,\n builtInRules,\n loadRules\n });\n }\n\n /**\n * The path to the current working directory.\n * This is used by tests.\n * @type {string}\n */\n get cwd() {\n const { cwd } = internalSlotsMap.get(this);\n\n return cwd;\n }\n\n /**\n * Get the config array of a given file.\n * If `filePath` was not given, it returns the config which contains only\n * `baseConfigData` and `cliConfigData`.\n * @param {string} [filePath] The file path to a file.\n * @param {Object} [options] The options.\n * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The config array of the file.\n */\n getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {\n const {\n baseConfigArray,\n cliConfigArray,\n cwd\n } = internalSlotsMap.get(this);\n\n if (!filePath) {\n return new ConfigArray(...baseConfigArray, ...cliConfigArray);\n }\n\n const directoryPath = path.dirname(path.resolve(cwd, filePath));\n\n debug(`Load config files for ${directoryPath}.`);\n\n return this._finalizeConfigArray(\n this._loadConfigInAncestors(directoryPath),\n directoryPath,\n ignoreNotFoundError\n );\n }\n\n /**\n * Set the config data to override all configs.\n * Require to call `clearCache()` method after this method is called.\n * @param {ConfigData} configData The config data to override all configs.\n * @returns {void}\n */\n setOverrideConfig(configData) {\n const slots = internalSlotsMap.get(this);\n\n slots.cliConfigData = configData;\n }\n\n /**\n * Clear config cache.\n * @returns {void}\n */\n clearCache() {\n const slots = internalSlotsMap.get(this);\n\n slots.baseConfigArray = createBaseConfigArray(slots);\n slots.cliConfigArray = createCLIConfigArray(slots);\n slots.configCache.clear();\n }\n\n /**\n * Load and normalize config files from the ancestor directories.\n * @param {string} directoryPath The path to a leaf directory.\n * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {\n const {\n baseConfigArray,\n configArrayFactory,\n configCache,\n cwd,\n useEslintrc\n } = internalSlotsMap.get(this);\n\n if (!useEslintrc) {\n return baseConfigArray;\n }\n\n let configArray = configCache.get(directoryPath);\n\n // Hit cache.\n if (configArray) {\n debug(`Cache hit: ${directoryPath}.`);\n return configArray;\n }\n debug(`No cache found: ${directoryPath}.`);\n\n const homePath = os.homedir();\n\n // Consider this is root.\n if (directoryPath === homePath && cwd !== homePath) {\n debug(\"Stop traversing because of considered root.\");\n if (configsExistInSubdirs) {\n const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);\n\n if (filePath) {\n emitDeprecationWarning(\n filePath,\n \"ESLINT_PERSONAL_CONFIG_SUPPRESS\"\n );\n }\n }\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n\n // Load the config on this directory.\n try {\n configArray = configArrayFactory.loadInDirectory(directoryPath);\n } catch (error) {\n /* istanbul ignore next */\n if (error.code === \"EACCES\") {\n debug(\"Stop traversing because of 'EACCES' error.\");\n return this._cacheConfig(directoryPath, baseConfigArray);\n }\n throw error;\n }\n\n if (configArray.length > 0 && configArray.isRoot()) {\n debug(\"Stop traversing because of 'root:true'.\");\n configArray.unshift(...baseConfigArray);\n return this._cacheConfig(directoryPath, configArray);\n }\n\n // Load from the ancestors and merge it.\n const parentPath = path.dirname(directoryPath);\n const parentConfigArray = parentPath && parentPath !== directoryPath\n ? this._loadConfigInAncestors(\n parentPath,\n configsExistInSubdirs || configArray.length > 0\n )\n : baseConfigArray;\n\n if (configArray.length > 0) {\n configArray.unshift(...parentConfigArray);\n } else {\n configArray = parentConfigArray;\n }\n\n // Cache and return.\n return this._cacheConfig(directoryPath, configArray);\n }\n\n /**\n * Freeze and cache a given config.\n * @param {string} directoryPath The path to a directory as a cache key.\n * @param {ConfigArray} configArray The config array as a cache value.\n * @returns {ConfigArray} The `configArray` (frozen).\n */\n _cacheConfig(directoryPath, configArray) {\n const { configCache } = internalSlotsMap.get(this);\n\n Object.freeze(configArray);\n configCache.set(directoryPath, configArray);\n\n return configArray;\n }\n\n /**\n * Finalize a given config array.\n * Concatenate `--config` and other CLI options.\n * @param {ConfigArray} configArray The parent config array.\n * @param {string} directoryPath The path to the leaf directory to find config files.\n * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.\n * @returns {ConfigArray} The loaded config.\n * @private\n */\n _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {\n const {\n cliConfigArray,\n configArrayFactory,\n finalizeCache,\n useEslintrc,\n builtInRules\n } = internalSlotsMap.get(this);\n\n let finalConfigArray = finalizeCache.get(configArray);\n\n if (!finalConfigArray) {\n finalConfigArray = configArray;\n\n // Load the personal config if there are no regular config files.\n if (\n useEslintrc &&\n configArray.every(c => !c.filePath) &&\n cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.\n ) {\n const homePath = os.homedir();\n\n debug(\"Loading the config file of the home directory:\", homePath);\n\n const personalConfigArray = configArrayFactory.loadInDirectory(\n homePath,\n { name: \"PersonalConfig\" }\n );\n\n if (\n personalConfigArray.length > 0 &&\n !directoryPath.startsWith(homePath)\n ) {\n const lastElement =\n personalConfigArray[personalConfigArray.length - 1];\n\n emitDeprecationWarning(\n lastElement.filePath,\n \"ESLINT_PERSONAL_CONFIG_LOAD\"\n );\n }\n\n finalConfigArray = finalConfigArray.concat(personalConfigArray);\n }\n\n // Apply CLI options.\n if (cliConfigArray.length > 0) {\n finalConfigArray = finalConfigArray.concat(cliConfigArray);\n }\n\n // Validate rule settings and environments.\n const validator = new ConfigValidator({\n builtInRules\n });\n\n validator.validateConfigArray(finalConfigArray);\n\n // Cache it.\n Object.freeze(finalConfigArray);\n finalizeCache.set(configArray, finalConfigArray);\n\n debug(\n \"Configuration was determined: %o on %s\",\n finalConfigArray,\n directoryPath\n );\n }\n\n // At least one element (the default ignore patterns) exists.\n if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {\n throw new ConfigurationNotFoundError(directoryPath);\n }\n\n return finalConfigArray;\n }\n}\n\n//------------------------------------------------------------------------------\n// Public Interface\n//------------------------------------------------------------------------------\n\nexport { CascadingConfigArrayFactory };\n","/**\n * @fileoverview Compatibility class for flat config.\n * @author Nicholas C. Zakas\n */\n\n//-----------------------------------------------------------------------------\n// Requirements\n//-----------------------------------------------------------------------------\n\nimport createDebug from \"debug\";\nimport path from \"path\";\n\nimport environments from \"../conf/environments.js\";\nimport { ConfigArrayFactory } from \"./config-array-factory.js\";\n\n//-----------------------------------------------------------------------------\n// Helpers\n//-----------------------------------------------------------------------------\n\n/** @typedef {import(\"../../shared/types\").Environment} Environment */\n/** @typedef {import(\"../../shared/types\").Processor} Processor */\n\nconst debug = createDebug(\"eslintrc:flat-compat\");\nconst cafactory = Symbol(\"cafactory\");\n\n/**\n * Translates an ESLintRC-style config object into a flag-config-style config\n * object.\n * @param {Object} eslintrcConfig An ESLintRC-style config object.\n * @param {Object} options Options to help translate the config.\n * @param {string} options.resolveConfigRelativeTo To the directory to resolve\n * configs from.\n * @param {string} options.resolvePluginsRelativeTo The directory to resolve\n * plugins from.\n * @param {ReadOnlyMap} options.pluginEnvironments A map of plugin environment\n * names to objects.\n * @param {ReadOnlyMap} options.pluginProcessors A map of plugin processor\n * names to objects.\n * @returns {Object} A flag-config-style config object.\n */\nfunction translateESLintRC(eslintrcConfig, {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo,\n pluginEnvironments,\n pluginProcessors\n}) {\n\n const flatConfig = {};\n const configs = [];\n const languageOptions = {};\n const linterOptions = {};\n const keysToCopy = [\"settings\", \"rules\", \"processor\"];\n const languageOptionsKeysToCopy = [\"globals\", \"parser\", \"parserOptions\"];\n const linterOptionsKeysToCopy = [\"noInlineConfig\", \"reportUnusedDisableDirectives\"];\n\n // copy over simple translations\n for (const key of keysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig[key] = eslintrcConfig[key];\n }\n }\n\n // copy over languageOptions\n for (const key of languageOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n\n // create the languageOptions key in the flat config\n flatConfig.languageOptions = languageOptions;\n\n if (key === \"parser\") {\n debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);\n\n if (eslintrcConfig[key].error) {\n throw eslintrcConfig[key].error;\n }\n\n languageOptions[key] = eslintrcConfig[key].definition;\n continue;\n }\n\n // clone any object values that are in the eslintrc config\n if (eslintrcConfig[key] && typeof eslintrcConfig[key] === \"object\") {\n languageOptions[key] = {\n ...eslintrcConfig[key]\n };\n } else {\n languageOptions[key] = eslintrcConfig[key];\n }\n }\n }\n\n // copy over linterOptions\n for (const key of linterOptionsKeysToCopy) {\n if (key in eslintrcConfig && typeof eslintrcConfig[key] !== \"undefined\") {\n flatConfig.linterOptions = linterOptions;\n linterOptions[key] = eslintrcConfig[key];\n }\n }\n\n // move ecmaVersion a level up\n if (languageOptions.parserOptions) {\n\n if (\"ecmaVersion\" in languageOptions.parserOptions) {\n languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;\n delete languageOptions.parserOptions.ecmaVersion;\n }\n\n if (\"sourceType\" in languageOptions.parserOptions) {\n languageOptions.sourceType = languageOptions.parserOptions.sourceType;\n delete languageOptions.parserOptions.sourceType;\n }\n\n // check to see if we even need parserOptions anymore and remove it if not\n if (Object.keys(languageOptions.parserOptions).length === 0) {\n delete languageOptions.parserOptions;\n }\n }\n\n // overrides\n if (eslintrcConfig.criteria) {\n flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];\n }\n\n // translate plugins\n if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === \"object\") {\n debug(`Translating plugins: ${eslintrcConfig.plugins}`);\n\n flatConfig.plugins = {};\n\n for (const pluginName of Object.keys(eslintrcConfig.plugins)) {\n\n debug(`Translating plugin: ${pluginName}`);\n debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);\n\n const { definition: plugin, error } = eslintrcConfig.plugins[pluginName];\n\n if (error) {\n throw error;\n }\n\n flatConfig.plugins[pluginName] = plugin;\n\n // create a config for any processors\n if (plugin.processors) {\n for (const processorName of Object.keys(plugin.processors)) {\n if (processorName.startsWith(\".\")) {\n debug(`Assigning processor: ${pluginName}/${processorName}`);\n\n configs.unshift({\n files: [`**/*${processorName}`],\n processor: pluginProcessors.get(`${pluginName}/${processorName}`)\n });\n }\n\n }\n }\n }\n }\n\n // translate env - must come after plugins\n if (eslintrcConfig.env && typeof eslintrcConfig.env === \"object\") {\n for (const envName of Object.keys(eslintrcConfig.env)) {\n\n // only add environments that are true\n if (eslintrcConfig.env[envName]) {\n debug(`Translating environment: ${envName}`);\n\n if (environments.has(envName)) {\n\n // built-in environments should be defined first\n configs.unshift(...translateESLintRC(environments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n } else if (pluginEnvironments.has(envName)) {\n\n // if the environment comes from a plugin, it should come after the plugin config\n configs.push(...translateESLintRC(pluginEnvironments.get(envName), {\n resolveConfigRelativeTo,\n resolvePluginsRelativeTo\n }));\n }\n }\n }\n }\n\n // only add if there are actually keys in the config\n if (Object.keys(flatConfig).length > 0) {\n configs.push(flatConfig);\n }\n\n return configs;\n}\n\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\n/**\n * A compatibility class for working with configs.\n */\nclass FlatCompat {\n\n constructor({\n baseDirectory = process.cwd(),\n resolvePluginsRelativeTo = baseDirectory,\n recommendedConfig,\n allConfig\n } = {}) {\n this.baseDirectory = baseDirectory;\n this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;\n this[cafactory] = new ConfigArrayFactory({\n cwd: baseDirectory,\n resolvePluginsRelativeTo,\n getEslintAllConfig: () => {\n\n if (!allConfig) {\n throw new TypeError(\"Missing parameter 'allConfig' in FlatCompat constructor.\");\n }\n\n return allConfig;\n },\n getEslintRecommendedConfig: () => {\n\n if (!recommendedConfig) {\n throw new TypeError(\"Missing parameter 'recommendedConfig' in FlatCompat constructor.\");\n }\n\n return recommendedConfig;\n }\n });\n }\n\n /**\n * Translates an ESLintRC-style config into a flag-config-style config.\n * @param {Object} eslintrcConfig The ESLintRC-style config object.\n * @returns {Object} A flag-config-style config object.\n */\n config(eslintrcConfig) {\n const eslintrcArray = this[cafactory].create(eslintrcConfig, {\n basePath: this.baseDirectory\n });\n\n const flatArray = [];\n let hasIgnorePatterns = false;\n\n eslintrcArray.forEach(configData => {\n if (configData.type === \"config\") {\n hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;\n flatArray.push(...translateESLintRC(configData, {\n resolveConfigRelativeTo: path.join(this.baseDirectory, \"__placeholder.js\"),\n resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, \"__placeholder.js\"),\n pluginEnvironments: eslintrcArray.pluginEnvironments,\n pluginProcessors: eslintrcArray.pluginProcessors\n }));\n }\n });\n\n // combine ignorePatterns to emulate ESLintRC behavior better\n if (hasIgnorePatterns) {\n flatArray.unshift({\n ignores: [filePath => {\n\n // Compute the final config for this file.\n // This filters config array elements by `files`/`excludedFiles` then merges the elements.\n const finalConfig = eslintrcArray.extractConfig(filePath);\n\n // Test the `ignorePattern` properties of the final config.\n return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);\n }]\n });\n }\n\n return flatArray;\n }\n\n /**\n * Translates the `env` section of an ESLintRC-style config.\n * @param {Object} envConfig The `env` section of an ESLintRC config.\n * @returns {Object[]} An array of flag-config objects representing the environments.\n */\n env(envConfig) {\n return this.config({\n env: envConfig\n });\n }\n\n /**\n * Translates the `extends` section of an ESLintRC-style config.\n * @param {...string} configsToExtend The names of the configs to load.\n * @returns {Object[]} An array of flag-config objects representing the config.\n */\n extends(...configsToExtend) {\n return this.config({\n extends: configsToExtend\n });\n }\n\n /**\n * Translates the `plugins` section of an ESLintRC-style config.\n * @param {...string} plugins The names of the plugins to load.\n * @returns {Object[]} An array of flag-config objects representing the plugins.\n */\n plugins(...plugins) {\n return this.config({\n plugins\n });\n }\n}\n\nexport { FlatCompat };\n","/**\n * @fileoverview Package exports for @eslint/eslintrc\n * @author Nicholas C. Zakas\n */\n//------------------------------------------------------------------------------\n// Requirements\n//------------------------------------------------------------------------------\n\nimport {\n ConfigArrayFactory,\n createContext as createConfigArrayFactoryContext\n} from \"./config-array-factory.js\";\n\nimport { CascadingConfigArrayFactory } from \"./cascading-config-array-factory.js\";\nimport * as ModuleResolver from \"./shared/relative-module-resolver.js\";\nimport { ConfigArray, getUsedExtractedConfigs } from \"./config-array/index.js\";\nimport { ConfigDependency } from \"./config-array/config-dependency.js\";\nimport { ExtractedConfig } from \"./config-array/extracted-config.js\";\nimport { IgnorePattern } from \"./config-array/ignore-pattern.js\";\nimport { OverrideTester } from \"./config-array/override-tester.js\";\nimport * as ConfigOps from \"./shared/config-ops.js\";\nimport ConfigValidator from \"./shared/config-validator.js\";\nimport * as naming from \"./shared/naming.js\";\nimport { FlatCompat } from \"./flat-compat.js\";\nimport environments from \"../conf/environments.js\";\n\n//-----------------------------------------------------------------------------\n// Exports\n//-----------------------------------------------------------------------------\n\nconst Legacy = {\n ConfigArray,\n createConfigArrayFactoryContext,\n CascadingConfigArrayFactory,\n ConfigArrayFactory,\n ConfigDependency,\n ExtractedConfig,\n IgnorePattern,\n OverrideTester,\n getUsedExtractedConfigs,\n environments,\n\n // shared\n ConfigOps,\n ConfigValidator,\n ModuleResolver,\n naming\n};\n\nexport {\n\n Legacy,\n\n FlatCompat\n\n};\n"],"names":["debug","debugOrig","path","ignore","assert","internalSlotsMap","util","minimatch","Ajv","globals","BuiltInEnvironments","ConfigOps.normalizeConfigGlobal","Module","require","createRequire","fs","stripComments","ModuleResolver.resolve","naming.normalizePackageName","naming.getShorthandName","os","createDebug","createConfigArrayFactoryContext"],"mappings":"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"} +\ No newline at end of file +diff --git a/lib/config-array-factory.js b/lib/config-array-factory.js +index 99851e15f9d79154e47cf6595c9b761ad1683401..bd6748c96eaa2d43ca05a6730486c726d47b0618 100644 +--- a/lib/config-array-factory.js ++++ b/lib/config-array-factory.js +@@ -40,7 +40,6 @@ + + import debugOrig from "debug"; + import fs from "fs"; +-import importFresh from "import-fresh"; + import { createRequire } from "module"; + import path from "path"; + import stripComments from "strip-json-comments"; +@@ -234,7 +233,7 @@ function loadLegacyConfigFile(filePath) { + function loadJSConfigFile(filePath) { + debug(`Loading JS config file: ${filePath}`); + try { +- return importFresh(filePath); ++ return require(filePath); + } catch (e) { + debug(`Error reading JavaScript file: ${filePath}`); + e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`; diff --git a/.yarn/patches/eslint-npm-8.20.0-6bbc377ff7.patch b/.yarn/patches/eslint-npm-8.36.0-f8482bce95.patch similarity index 71% rename from .yarn/patches/eslint-npm-8.20.0-6bbc377ff7.patch rename to .yarn/patches/eslint-npm-8.36.0-f8482bce95.patch index 03928a1ac..2c578fa65 100644 --- a/.yarn/patches/eslint-npm-8.20.0-6bbc377ff7.patch +++ b/.yarn/patches/eslint-npm-8.36.0-f8482bce95.patch @@ -1,8 +1,8 @@ diff --git a/lib/linter/linter.js b/lib/linter/linter.js -index 29d78da3969e2a3560d056af5683a08083562984..a6ae07b7142a353fcd8d58b55a7e68b8f81b2846 100644 +index 0f1bd4f77611aa5ccc43c94385efd4f9b5639327..59ff9f14727e22bbec2cc7539af30305f759b23a 100644 --- a/lib/linter/linter.js +++ b/lib/linter/linter.js -@@ -704,7 +704,7 @@ function createLanguageOptions({ globals: configuredGlobals, parser, parserOptio +@@ -708,7 +708,7 @@ function createLanguageOptions({ globals: configuredGlobals, parser, parserOptio */ function resolveGlobals(providedGlobals, enabledEnvironments) { return Object.assign( diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 2980e9ccb..b8b8c19df 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -695,10 +695,6 @@ "message": "$1 ist mit keiner Site verbunden.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1-Snap ist mit diesen Sites verbunden. Sie haben Zugriff auf die oben aufgeführten Berechtigungen.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Verbinden..." }, @@ -1355,18 +1351,6 @@ "message": "Dateiimport fehlgeschlagen? Bitte hier klicken!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Details ansehen", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Hinzugefügt am", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "von", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "Sie sollten diese Erweiterung deinstallieren", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Keine passenden Ergebnisse gefunden." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Zeigen" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Intelligente Transaktionen" }, - "snapAccess": { - "message": "$1-Snap hat Zugriff auf:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Am $1 von $2 hinzugefügt", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Diese Inhalte stammen von $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Verwalten Sie Ihre Snaps" }, - "snapsStatus": { - "message": "Snap-Status ist von der Aktivität abhängig." - }, "snapsToggle": { "message": "Ein Snap wird nur ausgeführt, wenn er aktiviert ist" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Was Sie beachten sollten:" }, - "thisIsBasedOn": { - "message": "Dies basiert auf Informationen von " - }, "time": { "message": "Zeit" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index f0836e464..06ebced86 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -695,10 +695,6 @@ "message": "$1 δεν είναι συνδεδεμένο με καμία τοποθεσία.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Το snap $1 συνδέεται με αυτούς τους ιστότοπους. Έχουν πρόσβαση στις παραπάνω άδειες.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Σύνδεση..." }, @@ -1355,18 +1351,6 @@ "message": "Η εισαγωγή αρχείων δεν λειτουργεί; Κάντε κλικ εδώ!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Προβολή λεπτομερειών", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Προστέθηκε στις", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "από", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "θα πρέπει να καταργήσετε την εγκατάσταση αυτής της επέκτασης", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Δε βρέθηκαν αποτελέσματα που να ταιριάζουν." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Εμφάνιση" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Έξυπνη Συναλλαγή" }, - "snapAccess": { - "message": "Το snap $1 έχει πρόσβαση σε:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Προστέθηκε στις $1 από $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Αυτό το περιεχόμενο προέρχεται από το $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Διαχειριστείτε τα Snaps σας" }, - "snapsStatus": { - "message": "Η κατάσταση του Snap εξαρτάται από τη δραστηριότητα." - }, "snapsToggle": { "message": "Ένα snap θα εκτελεστεί μόνο εάν είναι ενεργοποιημένο" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Πράγματα που πρέπει να έχετε υπόψη σας:" }, - "thisIsBasedOn": { - "message": "Αυτό βασίζεται σε πληροφορίες από" - }, "time": { "message": "Ώρα" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index cc1f96a56..1fae0fd7f 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -103,9 +103,6 @@ "SIWEWarningTitle": { "message": "Are you sure?" }, - "ShowMore": { - "message": "Show more" - }, "about": { "message": "About" }, @@ -333,6 +330,12 @@ "alerts": { "message": "Alerts" }, + "allCustodianAccountsConnectedSubtitle": { + "message": "You have either already connected all your custodian accounts or don’t have any account to connect to MetaMask Institutional." + }, + "allCustodianAccountsConnectedTitle": { + "message": "No accounts available to connect" + }, "allOfYour": { "message": "All of your $1", "description": "$1 is the symbol or name of the token that the user is approving spending" @@ -466,6 +469,9 @@ "average": { "message": "Average" }, + "awaitingApproval": { + "message": "Awaiting approval..." + }, "back": { "message": "Back" }, @@ -546,6 +552,9 @@ "message": "View account at $1", "description": "$1 replaced by URL for custom block explorer" }, + "blockaid": { + "message": "Blockaid" + }, "blockies": { "message": "Blockies" }, @@ -721,6 +730,12 @@ "connectAccountOrCreate": { "message": "Connect account or create new" }, + "connectCustodialAccountMsg": { + "message": "Please choose the custodian you want to connect in order to add or refresh a token." + }, + "connectCustodialAccountTitle": { + "message": "Custodial Accounts" + }, "connectHardwareWallet": { "message": "Connect hardware wallet" }, @@ -771,10 +786,6 @@ "message": "$1 is not connected to any sites.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 snap is connected to these sites. They have access to the permissions listed above.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Connecting..." }, @@ -936,6 +947,27 @@ "custodianAccount": { "message": "Custodian account" }, + "custodianReplaceRefreshTokenChangedFailed": { + "message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again." + }, + "custodianReplaceRefreshTokenChangedSubtitle": { + "message": "You can now use your custodian accounts in MetaMask Institutional." + }, + "custodianReplaceRefreshTokenChangedTitle": { + "message": "Your custodian token has been refreshed" + }, + "custodianReplaceRefreshTokenSubtitle": { + "message": "This is will replace the custodian token for the following address:" + }, + "custodianReplaceRefreshTokenTitle": { + "message": "Replace custodian token" + }, + "custodyApiUrl": { + "message": "$1 API URL" + }, + "custodyDeeplinkDescription": { + "message": "Approve the transaction in the $1 app. Once all required custody approvals have been performed the transaction will complete. Check your $1 app for status." + }, "custodyRefreshTokenModalDescription": { "message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again." }, @@ -951,6 +983,9 @@ "custodyRefreshTokenModalTitle": { "message": "Your custodian session has expired" }, + "custodySessionExpired": { + "message": "Custodian session expired." + }, "custom": { "message": "Advanced" }, @@ -1061,6 +1096,10 @@ "description": { "message": "Description" }, + "descriptionFromSnap": { + "message": "Description from $1", + "description": "$1 represents the name of the snap" + }, "desktopConnectionCriticalErrorDescription": { "message": "This error could be intermittent, so try restarting the extension or disable MetaMask Desktop." }, @@ -1325,6 +1364,9 @@ "enableSmartTransactions": { "message": "Enable smart transactions" }, + "enableSnap": { + "message": "Enable" + }, "enableToken": { "message": "enable $1", "description": "$1 is a token symbol, e.g. ETH" @@ -1361,6 +1403,9 @@ "enterANumber": { "message": "Enter a number" }, + "enterCustodianToken": { + "message": "Enter your $1 token or add a new token" + }, "enterMaxSpendLimit": { "message": "Enter max spend limit" }, @@ -1370,6 +1415,9 @@ "enterPasswordContinue": { "message": "Enter password to continue" }, + "enterYourPassword": { + "message": "Enter your password" + }, "errorCode": { "message": "Code: $1", "description": "Displayed error code for debugging purposes. $1 is the error code" @@ -1475,18 +1523,6 @@ "fileTooBig": { "message": "The dropped file is too big." }, - "flaskSnapSettingsCardButtonCta": { - "message": "See details", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Added on", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "from", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "you should uninstall this extension", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -1630,6 +1666,12 @@ "general": { "message": "General" }, + "globalTitle": { + "message": "Global menu" + }, + "globalTourDescription": { + "message": "See your portfolio, connected sites, settings, and more" + }, "goBack": { "message": "Go back" }, @@ -1843,6 +1885,13 @@ "install": { "message": "Install" }, + "installOrigin": { + "message": "Install origin" + }, + "installedOn": { + "message": "Installed on $1", + "description": "$1 is the date when the snap has been installed" + }, "institutionalFeatures": { "message": "Institutional Features" }, @@ -1971,6 +2020,9 @@ "message": "Want to $1 about gas?", "description": "$1 will be replaced by the learnMore translation key" }, + "learnMoreKeystone": { + "message": "Learn More" + }, "learnMoreUpperCase": { "message": "Learn more" }, @@ -1987,16 +2039,16 @@ "message": "Prior to clicking confirm:" }, "ledgerConnectionInstructionStepFour": { - "message": "Enable \"smart contract data\" or \"blind signing\" on your Ledger device" + "message": "Enable \"smart contract data\" or \"blind signing\" on your Ledger device." }, "ledgerConnectionInstructionStepOne": { - "message": "Enable Use Ledger Live under Settings > Advanced" + "message": "Enable Use Ledger Live under Settings > Advanced." }, "ledgerConnectionInstructionStepThree": { - "message": "Plug in your Ledger device and select the Ethereum app" + "message": "Be sure your Ledger is plugged in and to select the Ethereum app." }, "ledgerConnectionInstructionStepTwo": { - "message": "Open and unlock Ledger Live App" + "message": "Open and unlock Ledger Live App." }, "ledgerConnectionPreferenceDescription": { "message": "Customize how you connect your Ledger to MetaMask. $1 is recommended, but other options are available. Read more here: $2", @@ -2143,6 +2195,9 @@ "metrics": { "message": "Metrics" }, + "mismatchAccount": { + "message": "Your selected account ($1) is different than the account trying to sign ($2)" + }, "mismatchedChainLinkText": { "message": "verify the network details", "description": "Serves as link text for the 'mismatchedChain' key. This text will be embedded inside the translation for that key." @@ -2181,6 +2236,9 @@ "mmiAuthenticate": { "message": "The page at $1 would like to authorise the following project’s compliance settings in MetaMask Institutional" }, + "more": { + "message": "more" + }, "moreComingSoon": { "message": "More coming soon..." }, @@ -2229,6 +2287,9 @@ "networkIsBusy": { "message": "Network is busy. Gas prices are high and estimates are less accurate." }, + "networkMenu": { + "message": "Network Menu" + }, "networkMenuHeading": { "message": "Select a network" }, @@ -2393,6 +2454,9 @@ "noNFTs": { "message": "No NFTs yet" }, + "noReport": { + "message": "No Report" + }, "noSnaps": { "message": "You don't have any snaps installed." }, @@ -2795,18 +2859,21 @@ "message": "Open Codefi Compliance" }, "openFullScreenForLedgerWebHid": { - "message": "Open MetaMask in full screen to connect your ledger via WebHID.", + "message": "Go to full screen to connect your Ledger.", "description": "Shown to the user on the confirm screen when they are viewing MetaMask in a popup window but need to connect their ledger via webhid." }, "openInBlockExplorer": { "message": "Open in block explorer" }, "openSea": { - "message": "OpenSea (Beta)" + "message": "OpenSea + Blockaid (Beta)" }, "openSeaNew": { "message": "OpenSea" }, + "operationFailed": { + "message": "Operation Failed" + }, "optional": { "message": "Optional" }, @@ -2866,6 +2933,9 @@ "passwordsDontMatch": { "message": "Passwords don't match" }, + "pasteJWTToken": { + "message": "Paste or drop your token here:" + }, "pastePrivateKey": { "message": "Enter your private key string here:", "description": "For importing an account from a private key" @@ -3046,6 +3116,12 @@ "permissions": { "message": "Permissions" }, + "permissionsTitle": { + "message": "Permissions" + }, + "permissionsTourDescription": { + "message": "Find your connected accounts and manage permissions here" + }, "personalAddressDetected": { "message": "Personal address detected. Input the token contract address." }, @@ -3097,6 +3173,10 @@ "message": "Private Key", "description": "select this type of file to use to import an account" }, + "privateKeyCopyWarning": { + "message": "Private key for $1", + "description": "$1 represents the account name" + }, "privateKeyWarning": { "message": "Warning: Never disclose this key. Anyone with your private keys can steal any assets held in your account." }, @@ -3208,6 +3288,12 @@ "removeAccountDescription": { "message": "This account will be removed from your wallet. Please make sure you have the original Secret Recovery Phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. " }, + "removeJWT": { + "message": "Remove custodian token" + }, + "removeJWTDescription": { + "message": "Are you sure you want to remove this token? All accounts assigned to this token will be removed from extension as well: " + }, "removeNFT": { "message": "Remove NFT" }, @@ -3227,6 +3313,12 @@ "replace": { "message": "replace" }, + "reportLastRun": { + "message": "Report last run" + }, + "reportLastRunTooltip": { + "message": "The date and time of when the last AML/CFT report was run" + }, "requestFailed": { "message": "Request failed" }, @@ -3356,9 +3448,18 @@ "revokeSpendingCapTooltipText": { "message": "This third party will be unable to spend any more of your current or future tokens." }, + "riskRating": { + "message": "Risk rating" + }, + "riskRatingTooltip": { + "message": "The risk rating of the address you are interacting with based on your risk settings" + }, "rpcUrl": { "message": "New RPC URL" }, + "runReport": { + "message": "Run report" + }, "safeTransferFrom": { "message": "Safe transfer from" }, @@ -3398,6 +3499,9 @@ "security": { "message": "Security" }, + "securityAlert": { + "message": "Security alert from $1 and $2" + }, "securityAndPrivacy": { "message": "Security & privacy" }, @@ -3455,18 +3559,27 @@ "seedPhraseWriteDownHeader": { "message": "Write down your Secret Recovery Phrase" }, + "select": { + "message": "Select" + }, "selectAccounts": { "message": "Select the account(s) to use on this site" }, "selectAll": { "message": "Select all" }, + "selectAllAccounts": { + "message": "Select all accounts" + }, "selectAnAccount": { "message": "Select an account" }, "selectAnAccountAlreadyConnected": { "message": "This account has already been connected to MetaMask" }, + "selectAnAccountHelp": { + "message": "Select the custodian accounts to use in MetaMask Institutional." + }, "selectHdPath": { "message": "Select HD path" }, @@ -3538,9 +3651,9 @@ "settingsSearchMatchingNotFound": { "message": "No matching results found." }, - "shorthandVersion": { + "shortVersion": { "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" + "description": "$1 is the version number to show" }, "show": { "message": "Show" @@ -3567,12 +3680,21 @@ "message": "This relies on $1 which will have access to your Ethereum address and your IP address. $2", "description": "$1 is the link to etherscan url and $2 is the link to the privacy policy of consensys APIs" }, + "showMore": { + "message": "Show more" + }, "showPermissions": { "message": "Show permissions" }, + "showPrivateKey": { + "message": "Show private key" + }, "showPrivateKeys": { "message": "Show Private Keys" }, + "showReport": { + "message": "Show report" + }, "showTestnetNetworks": { "message": "Show test networks" }, @@ -3615,14 +3737,6 @@ "smartTransaction": { "message": "Smart transaction" }, - "snapAccess": { - "message": "$1 snap has access to:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Added on $1 from $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "This content is coming from $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3643,7 +3757,7 @@ "description": "$1 is the dApp origin requesting the snap and $2 is the snap name" }, "snapInstallWarningCheck": { - "message": "Ensure that the permission below align with your intended actions. Only proceed with authors you trust." + "message": "Ensure that the permission below aligns with your intended actions. Only proceed with authors you trust." }, "snapInstallWarningCheckPlural": { "message": "Ensure that the permissions below align with your intended actions. Only proceed with authors you trust." @@ -3694,9 +3808,6 @@ "snapsSettingsDescription": { "message": "Manage your Snaps" }, - "snapsStatus": { - "message": "Snap status is dependent on activity." - }, "snapsToggle": { "message": "A snap will only run if it is enabled" }, @@ -3790,6 +3901,9 @@ "stableLowercase": { "message": "stable" }, + "stake": { + "message": "Stake" + }, "stateLogError": { "message": "Error in retrieving state logs." }, @@ -4270,6 +4384,12 @@ "switchedTo": { "message": "You have switched to" }, + "switcherTitle": { + "message": "Network switcher" + }, + "switcherTourDescription": { + "message": "Click the icon to switch networks or add a new network" + }, "switchingNetworksCancelsPendingConfirmations": { "message": "Switching networks will cancel all pending confirmations" }, @@ -4315,9 +4435,6 @@ "thisCollection": { "message": "this collection" }, - "thisIsBasedOn": { - "message": "This is based on information from " - }, "thisServiceIsExperimental": { "message": "This service is experimental. By enabling this feature, you agree to OpenSea's $1.", "description": "$1 is link to open sea terms of use" @@ -4335,11 +4452,44 @@ "message": "To: $1", "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" }, + "toggleEthSignBannerDescription": { + "message": "You’re at risk for phishing attacks. Protect yourself by turning off eth_sign." + }, "toggleEthSignDescriptionField": { - "message": "Turn this on to let dapps request your signature using eth_sign requests. eth_sign is an open-ended signing method that lets you sign an arbitrary hash, making it a dangerous phishing risk. Only sign eth_sign requests if you can read what you are signing and trust the origin of the request." + "message": "If you enable this setting, you might get signature requests that aren’t readable. By signing a message you don't understand, you could be agreeing to give away your funds and NFTs." }, "toggleEthSignField": { - "message": "Toggle eth_sign requests" + "message": "Eth_sign requests" + }, + "toggleEthSignModalBannerBoldText": { + "message": " you might be getting scammed" + }, + "toggleEthSignModalBannerText": { + "message": "If you've been asked to turn this setting on," + }, + "toggleEthSignModalCheckBox": { + "message": "I understand that I can lose all of my funds and NFTs if I enable eth_sign requests. " + }, + "toggleEthSignModalDescription": { + "message": "Allowing eth_sign requests can make you vulnerable to phishing attacks. Always review the URL and be careful when signing messages that contain code." + }, + "toggleEthSignModalFormError": { + "message": "The text is incorrect" + }, + "toggleEthSignModalFormLabel": { + "message": "Enter “I only sign what I understand” to continue" + }, + "toggleEthSignModalFormValidation": { + "message": "I only sign what I understand" + }, + "toggleEthSignModalTitle": { + "message": "Use at your own risk" + }, + "toggleEthSignOff": { + "message": "OFF (Recommended)" + }, + "toggleEthSignOn": { + "message": "ON (Not recommended)" }, "toggleTestNetworks": { "message": "$1 test networks", @@ -4472,6 +4622,9 @@ "transactionErrored": { "message": "Transaction encountered an error." }, + "transactionFailed": { + "message": "Transaction Failed" + }, "transactionFee": { "message": "Transaction fee" }, @@ -4500,7 +4653,7 @@ "message": "Transaction resubmitted with estimated gas fee increased to $1 at $2" }, "transactionSecurityCheck": { - "message": "Enable transaction security providers" + "message": "Enable security alerts" }, "transactionSecurityCheckDescription": { "message": "We use third-party APIs to detect and display risks involved in unsigned transaction and signature requests before you sign them. These services will have access to your unsigned transaction and signature requests, your account address, and your preferred language." @@ -4698,6 +4851,9 @@ "message": "Verify this token on $1 and make sure this is the token you want to trade.", "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, + "version": { + "message": "Version" + }, "view": { "message": "View" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index bf0aab118..67a3b012a 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -695,10 +695,6 @@ "message": "$1 no está conectado a ningún sitio.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "El complemento de $1 está conectado a estos sitios. Tienen acceso a los permisos enumerados anteriormente.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Estableciendo conexión…" }, @@ -1355,18 +1351,6 @@ "message": "¿No funciona la importación del archivo? Haga clic aquí.", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Ver detalles", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Añadido el", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "de", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "le recomendamos que desinstale esta extensión", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "No se encontraron resultados coincidentes." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Mostrar" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Transacción inteligente" }, - "snapAccess": { - "message": "El complemento de $1 tiene acceso a:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Se agregó en $1 de $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Este contenido proviene de $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Administre sus complementos" }, - "snapsStatus": { - "message": "El estado del complemento depende de la actividad." - }, "snapsToggle": { "message": "Un complemento solo se ejecutará si está habilitado" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Cosas a tener en cuenta:" }, - "thisIsBasedOn": { - "message": "Esto se basa en información de " - }, "time": { "message": "Tiempo" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index e46218f14..98254c6fc 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -882,18 +882,6 @@ "message": "¿No funciona la importación del archivo? ¡Haga clic aquí!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Ver detalles", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Añadido el", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "de", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "le recomendamos que desinstale esta extensión", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 1d2319533..b543b2114 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -695,10 +695,6 @@ "message": "$1 n’est connecté à aucun site.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Le snap $1 est connecté à ces sites. Ils ont accès aux autorisations énumérées ci-dessus.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Connexion…" }, @@ -1355,18 +1351,6 @@ "message": "L’importation de fichier ne fonctionne pas ? Cliquez ici !", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Voir les détails", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Ajouté le", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "de", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "vous devriez désinstaller cette extension", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Aucun résultat correspondant trouvé." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Afficher" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Transaction intelligente" }, - "snapAccess": { - "message": "Le snap $1 peut accéder à :", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Ajouté le $1 à partir de $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Ce contenu provient de $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Gérez vos Snaps" }, - "snapsStatus": { - "message": "L’état du Snap dépend de l’activité." - }, "snapsToggle": { "message": "Un snap ne s’exécute que s’il est activé" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Les choses que vous devez garder à l’esprit :" }, - "thisIsBasedOn": { - "message": "Ces informations proviennent de " - }, "time": { "message": "Temps" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 05c32e878..e9781a768 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -695,10 +695,6 @@ "message": "$1 किसी भी साइट से कनेक्ट नहीं है।", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 स्नैप इन साइटों से जुड़ा है। वे ऊपर सूचीबद्ध अनुमतियों को एक्सेस कर सकती हैं।", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "कनेक्ट किया जा रहा है..." }, @@ -1355,18 +1351,6 @@ "message": "फाइल आयात काम नहीं कर रहा है? यहां क्लिक करें!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "विवरण देखें", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "जोड़ा गया", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "से", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "आपको इस एक्सटेन्शन को अनइंस्टाल करना चाहिए", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "कोई मेल खाने वाला परिणाम नहीं मिला।" }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "दिखाएं" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "स्मार्ट लेनदेन" }, - "snapAccess": { - "message": "$1 स्नैप को एक्सेस है:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "$2 से $1 जोड़ा गया", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "यह सामग्री $1 से आ रही है", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "अपने स्नैप्स प्रबंधित करें" }, - "snapsStatus": { - "message": "स्नैप स्टेटस एक्टिविटी पर निर्भर करता है।" - }, "snapsToggle": { "message": "कोई स्नैप तभी चलेगा जब उसे सक्षम किया गया हो" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "ध्यान रखने योग्य बातें" }, - "thisIsBasedOn": { - "message": "से प्राप्त जानकारी पर आधारित है" - }, "time": { "message": "समय" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 5153bebde..97df69b6f 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -695,10 +695,6 @@ "message": "$1 tidak terhubung ke situs mana pun.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Snap $1 terhubung ke situs-situs ini. Token ini memiliki akses ke izin yang tercantum di atas. \t", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Menghubungkan..." }, @@ -1355,18 +1351,6 @@ "message": "Impor file tidak bekerja? Klik di sini!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Lihat detailnya", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Ditambahkan di", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "dari", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "Anda harus menghapus ekstensi ini", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Tidak menemukan hasil yang cocok." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Tampil" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Transaksi pintar" }, - "snapAccess": { - "message": "Snap $1 memiliki akses ke:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Ditambahkan pada $1 dari $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Konten ini berasal dari $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Kelola Snap Anda" }, - "snapsStatus": { - "message": "Status snap tergantung pada aktivitas." - }, "snapsToggle": { "message": "Snap hanya akan beroperasi jika diaktifkan" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Hal-hal yang perlu diingat:" }, - "thisIsBasedOn": { - "message": "Hal ini berdasarkan informasi dari " - }, "time": { "message": "Waktu" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 6ed51025d..fc9e9a4d1 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -538,10 +538,6 @@ "message": "$1 non è connesso ad alcun sito.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 snap è collegato a questi siti. Hanno accesso alle autorizzazioni sopra elencate.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Connessione..." }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 285805237..a3c0dd28e 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -695,10 +695,6 @@ "message": "$1はどのサイトとも接続されていません。", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 スナップはこれらのサイトに接続されており、上記のパーミッションにアクセスできます。", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "接続中..." }, @@ -1355,18 +1351,6 @@ "message": "ファイルのインポートが機能していない場合ここをクリックしてください!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "詳細を表示", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "追加日", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "元", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "この拡張機能はアンインストールしてください", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "一致する結果が見つかりませんでした。" }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "表示" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "スマートトランザクション" }, - "snapAccess": { - "message": "$1 スナップは次にアクセス可能です:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "$1 に $2 から追加", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "このコンテンツは $1 からのものです", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "スナップの管理" }, - "snapsStatus": { - "message": "スナップのステータスはアクティビティによります。" - }, "snapsToggle": { "message": "スナップは有効になっている場合にのみ実行されます" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "留意点:" }, - "thisIsBasedOn": { - "message": "これは次の情報源からの情報に基づくものです: " - }, "time": { "message": "時間" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index fe2d20dc6..c4de64fc4 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -695,10 +695,6 @@ "message": "$1 계정은 어떤 사이트에도 연결되어 있지 않습니다.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 스냅이 이 사이트에 연결되어 있습니다. 이 사이트는 위에 나열된 접근 권한이 있습니다.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "연결 중..." }, @@ -918,10 +914,10 @@ "message": "소수점 이하 자릿수는 0 이상, 36 이하여야 합니다." }, "decrypt": { - "message": "암호 해독" + "message": "복호화" }, "decryptCopy": { - "message": "암호 해독된 메시지 복사" + "message": "복호화된 메시지 복사" }, "decryptInlineError": { "message": "다음 오류 때문에 이 메시지를 해독할 수 없습니다: $1", @@ -1355,18 +1351,6 @@ "message": "파일 가져오기가 작동하지 않나요? 여기를 클릭하세요.", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "세부 정보 보기", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "추가하기", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "발신", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "이 확장 프로그램을 삭제해야 합니다", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -2173,7 +2157,7 @@ "message": "다음" }, "nextNonceWarning": { - "message": "임시값이 권장 임시값인 $1보다 큽니다.", + "message": "논스값이 권장 논스값인 $1보다 큽니다.", "description": "The next nonce according to MetaMask's internal logic" }, "nftAddFailedMessage": { @@ -2240,13 +2224,13 @@ "message": "웹캠을 찾을 수 없음" }, "nonce": { - "message": "임시값" + "message": "논스" }, "nonceField": { - "message": "거래 임시값 맞춤화" + "message": "거래 논스 맞춤화" }, "nonceFieldDescription": { - "message": "이 기능을 켜면 확인 화면에서 임시값(거래 번호)을 변경할 수 있습니다. 이는 고급 기능으로, 주의해서 사용해야 합니다." + "message": "이 기능을 켜면 확인 화면에서 논스(거래 번호)를 변경할 수 있습니다. 이는 고급 기능으로, 주의해서 사용해야 합니다." }, "nonceFieldHeading": { "message": "커스텀 논스" @@ -2346,7 +2330,7 @@ "description": "The 'call to action' on the button, or link, of the 'Swap on Binance Smart Chain!' notification. Upon clicking, users will be taken to a page where then can swap tokens on Binance Smart Chain." }, "notifications4Description": { - "message": "토큰 스왑 최고가를 지갑에서 바로 이용하세요. MetaMask는 이제 바이낸스 스마트 체인의 여러 분산형 교환 애그리게이터 및 투자전문기관과 연결됩니다.", + "message": "토큰 스왑 최고가를 지갑에서 바로 이용하세요. MetaMask는 이제 바이낸스 스마트 체인의 여러 탈중앙화 거래소 애그리게이터 및 투자전문기관과 연결됩니다.", "description": "Description of a notification in the 'See What's New' popup." }, "notifications4Title": { @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "검색 결과가 없습니다." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "보기" }, @@ -3284,7 +3264,7 @@ "message": "본 메시지에 서명하는 행위는 위험의 가능성을 내포하고 있습니다. 본 서명을 통해 메시지 발신 당사자에게 귀하의 계정 및 모든 자산에 대해 완전한 권한을 부여할 수 있기 때문입니다. 이를 통해 계정의 모든 잔액을 인출할 수 있기도 하다는 뜻입니다. 주의하여 진행하세요. $1" }, "signed": { - "message": "서명완료" + "message": "서명 완료" }, "signin": { "message": "로그인" @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "스마트 트랜잭션" }, - "snapAccess": { - "message": "$1 스냅이 접근할 수 있는 대상:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "$1에 $2에서 추가됨", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "콘텐츠 출처: $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "스냅 관리" }, - "snapsStatus": { - "message": "스냅 상태는 활동에 따라 달라집니다." - }, "snapsToggle": { "message": "스냅은 활성화된 상태에서만 작동합니다." }, @@ -3606,7 +3575,7 @@ "message": "보장 금액" }, "swapAmountReceivedInfo": { - "message": "수신하는 최소 금액입니다. 슬리패지에 따라 추가 금액을 받을 수도 있습니다." + "message": "수신하는 최소 금액입니다. 슬리피지에 따라 추가 금액을 받을 수도 있습니다." }, "swapApproval": { "message": "스왑을 위해 $1 승인", @@ -3637,7 +3606,7 @@ "message": "맞춤형" }, "swapDecentralizedExchange": { - "message": "분산형 교환" + "message": "탈중앙화 거래소" }, "swapDirectContract": { "message": "직접 계약" @@ -3700,17 +3669,17 @@ "description": "$1 is the selected network, e.g. Ethereum or BSC" }, "swapHighSlippageWarning": { - "message": "슬리패지 금액이 아주 큽니다." + "message": "슬리피지 금액이 아주 큽니다." }, "swapIncludesMMFee": { "message": "$1%의 MetaMask 요금이 포함됩니다.", "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." }, "swapLowSlippageError": { - "message": "거래가 실패할 수도 있습니다. 최대 슬리패지가 너무 낮습니다." + "message": "거래가 실패할 수도 있습니다. 최대 슬리피지가 너무 낮습니다." }, "swapMaxSlippage": { - "message": "최대 슬리패지" + "message": "최대 슬리피지" }, "swapMetaMaskFee": { "message": "MetaMask 수수료" @@ -3746,7 +3715,7 @@ "message": "시장 가격 데이터가 부족하여 가격 영향을 파악할 수 없습니다. 스왑하기 전에 받게 될 토큰 수가 만족스러운지 확인하시기 바랍니다." }, "swapPriceUnavailableTitle": { - "message": "진행하기 전에 요율 확인" + "message": "진행하기 전에 비율 확인" }, "swapProcessing": { "message": "처리 중" @@ -3758,25 +3727,25 @@ "message": "견적 소스" }, "swapQuotesExpiredErrorDescription": { - "message": "새 견적을 요청해 최신 요율을 확인하세요." + "message": "새 견적을 요청해 최신 비율을 확인하세요." }, "swapQuotesExpiredErrorTitle": { "message": "견적 시간 초과" }, "swapQuotesNotAvailableErrorDescription": { - "message": "금액 또는 슬리패지 설정을 조정한 후 다시 시도해 보세요." + "message": "금액 또는 슬리피지 설정을 조정한 후 다시 시도해 보세요." }, "swapQuotesNotAvailableErrorTitle": { "message": "사용 가능한 견적 없음" }, "swapRate": { - "message": "요율" + "message": "비율" }, "swapReceiving": { "message": "수신 중" }, "swapReceivingInfoTooltip": { - "message": "이것은 예상치입니다. 정확한 금액은 슬리패지에 따라 달라집니다." + "message": "이것은 예상치입니다. 정확한 금액은 슬리피지에 따라 달라집니다." }, "swapRequestForQuotation": { "message": "견적 요청" @@ -3800,20 +3769,20 @@ "message": "다음은 여러 유동성 소스에서 수집한 전체 견적입니다." }, "swapSlippageNegative": { - "message": "슬리패지는 0보다 크거나 같아야 합니다." + "message": "슬리피지는 0보다 크거나 같아야 합니다." }, "swapSlippagePercent": { "message": "$1%", "description": "$1 is the amount of % for slippage" }, "swapSlippageTooltip": { - "message": "주문 시점과 확인 시점 사이에 가격이 변동되는 현상을 \"슬리패지\"라고 합니다. 슬리패지가 \"최대 슬리패지\" 설정을 초과하면 스왑이 자동으로 취소됩니다." + "message": "주문 시점과 확인 시점 사이에 가격이 변동되는 현상을 \"슬리피지\"라고 합니다. 슬리피지가 \"최대 슬리피지\" 설정을 초과하면 스왑이 자동으로 취소됩니다." }, "swapSource": { "message": "유동성 소스" }, "swapSourceInfo": { - "message": "저희는 여러 유동성 소스(교환, 애그리게이터, 투자전문기관)를 검색하여 최상의 요율과 최저 네트워크 수수료를 찾아드립니다." + "message": "저희는 여러 유동성 소스(교환, 애그리게이터, 투자전문기관)를 검색하여 최상의 비율과 최저 네트워크 수수료를 찾아드립니다." }, "swapSuggested": { "message": "제안 스왑" @@ -3881,13 +3850,13 @@ "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" }, "swapZeroSlippage": { - "message": "0% 슬리패지" + "message": "0% 슬리피지" }, "swapsAdvancedOptions": { "message": "고급 옵션" }, "swapsExcessiveSlippageWarning": { - "message": "슬리패지 금액이 너무 커서 전환율이 좋지 않습니다. 슬리패지 허용치를 15% 값 이하로 줄이세요." + "message": "슬리피지 금액이 너무 커서 전환율이 좋지 않습니다. 슬리피지 허용치를 15% 값 이하로 줄이세요." }, "swapsMaxSlippage": { "message": "슬리피지 허용치" @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "유의 사항:" }, - "thisIsBasedOn": { - "message": "다음에 기반한 정보입니다: " - }, "time": { "message": "시간" }, @@ -4294,7 +4260,7 @@ "message": "연락처 정보 인증" }, "verifyThisTokenDecimalOn": { - "message": "토큰 십진수는 $1에서 찾을 수 있습니다.", + "message": "토큰 소수점은 $1에서 찾을 수 있습니다.", "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "verifyThisTokenOn": { diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index fac9a765a..d52ed995d 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -695,10 +695,6 @@ "message": "$1 não está conectada a nenhum site.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "O snap $1 está conectado a estes sites. Eles têm acesso às permissões listadas acima.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Conectando..." }, @@ -1355,18 +1351,6 @@ "message": "A importação de ficheiro não está a funcionar? Carregue aqui!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Ver detalhes", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Adicionado em", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "de", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "você deve desinstalar essa extensão", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Nenhum resultado correspondente encontrado." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Exibir" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Transação inteligente" }, - "snapAccess": { - "message": "Snap $1 tem acesso a:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Adicionado em $1 a partir de $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Esse conteúdo vem de $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Gerencie seus snaps" }, - "snapsStatus": { - "message": "O status do snap depende da atividade." - }, "snapsToggle": { "message": "O snap só será executado se estiver ativado" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Informações importantes:" }, - "thisIsBasedOn": { - "message": "Isso se baseia em informações de " - }, "time": { "message": "Hora" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 73ec8f5c3..6c949ccfc 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -882,18 +882,6 @@ "message": "A importação de arquivo não está funcionando? Clique aqui!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Ver detalhes", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Adicionado em", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "de", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "você deve desinstalar essa extensão", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index d332888b5..1b9a1a6e8 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -695,10 +695,6 @@ "message": "$1 не подключен ни к каким сайтам.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Снап $1 подключен к этим сайтам. У них есть доступ к перечисленным выше разрешениям.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Подключение..." }, @@ -1355,18 +1351,6 @@ "message": "Импорт файлов не работает? Нажмите здесь!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "См. подробности", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Добавлена", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "от", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "вам нужно должны удалить это расширение", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Совпадений не найдено." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Показать" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Смарт-транзакция" }, - "snapAccess": { - "message": "У снапа $1 есть доступ к:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Добавлено на $1 из $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Этот контент поступает от $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Управление вашим снапами" }, - "snapsStatus": { - "message": "Статус снапа зависит от активности." - }, "snapsToggle": { "message": "Снап будет работать только в том случае, если он включен" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Что нужно помнить:" }, - "thisIsBasedOn": { - "message": "Это основано на информации от " - }, "time": { "message": "Время" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 33fef9c73..479683256 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -695,10 +695,6 @@ "message": "Ang $1 ay hindi nakakonekta sa anumang site.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Ang $1 snap ay konektado sa mga site na ito. May access sila sa mga pahintulot na nakalista sa itaas.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Kumokonekta..." }, @@ -1355,18 +1351,6 @@ "message": "Hindi gumagana ang pag-import ng file? Mag-click dito!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Tingnan ang mga detalye", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Dinagdag sa", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "mula sa", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "dapat mong i-uninstall ang extension na ito", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Walang nakitang katugmang resulta." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Ipakita" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Smart Transaction" }, - "snapAccess": { - "message": "Ang $1 snap ay may access sa:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Idinagdag noong $1 mula sa $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Ang nilalamang ito ay nagmumula sa $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Pamahalaan ang iyong mga Snap" }, - "snapsStatus": { - "message": "Ang lagay ng Snap ay nakadepende sa aktibidad." - }, "snapsToggle": { "message": "Tatakbo lamang ang snap kapag pinagana ito" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Mga bagay na dapat tandaan:" }, - "thisIsBasedOn": { - "message": "Ito ay batay sa impormasyon mula sa " - }, "time": { "message": "Oras" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index ef089de79..1479da53f 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -695,10 +695,6 @@ "message": "$1 herhangi bir siteye bağlanmamış.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1 snap bu sitelere bağlı. Yukarıda listelenen izinlere erişimleri vardır.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Bağlanıyor..." }, @@ -1355,18 +1351,6 @@ "message": "Dosya içe aktarma çalışmıyor mu? Buraya tıklayın!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Ayrıntıları gör", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Şu tarihte eklendi:", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "şurada:", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "bu uzantıyı kaldırmalısın", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Eşleşen sonuç bulunamadı." }, - "shorthandVersion": { - "message": "s$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Göster" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Akıllı işlem" }, - "snapAccess": { - "message": "$1 snap'in şunlara erişimi vardır:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "$1 tarihinde $2 alanından eklendi", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Bu içerik $1 kaynaklıdır", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Snap'lerini yönet" }, - "snapsStatus": { - "message": "Snap durumu etkinliğe bağlıdır." - }, "snapsToggle": { "message": "Bir snap yalnızca etkinleştirilmişse çalışır" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Unutulmaması gerekenler:" }, - "thisIsBasedOn": { - "message": "Bu, şu kaynaktan alınan bilgilere dayanır: " - }, "time": { "message": "Zaman" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 4ce8446bd..4bb67b89e 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -695,10 +695,6 @@ "message": "$1 chưa được kết nối với bất kỳ trang web nào.", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "Snap $1 được kết nối với các trang web này. Các trang web này được phép sử dụng những quyền được liệt kê ở trên.", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "Đang kết nối..." }, @@ -1355,18 +1351,6 @@ "message": "Tính năng nhập tập tin không hoạt động? Nhấn vào đây!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "Xem chi tiết", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "Đã thêm vào", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "từ", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "bạn nên gỡ cài đặt tiện ích mở rộng này", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "Không tìm thấy kết quả trùng khớp." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "Hiển thị" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "Giao dịch thông minh" }, - "snapAccess": { - "message": "Snap $1 có quyền truy cập vào:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "Đã thêm vào $1 từ $2", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "Nội dung này đến từ $1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "Quản lý Snap" }, - "snapsStatus": { - "message": "Trạng thái Snap tùy thuộc vào hoạt động." - }, "snapsToggle": { "message": "Snap chỉ hoạt động khi đã bật" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "Những điều cần lưu ý:" }, - "thisIsBasedOn": { - "message": "Điều này dựa trên thông tin từ " - }, "time": { "message": "Thời gian" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index c7463ae0c..3bbbf0165 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -427,7 +427,7 @@ "message": "设置 MetaMask 将被锁定前的空闲时间(单位:分钟)。" }, "average": { - "message": "平均值" + "message": "中等" }, "back": { "message": "返回" @@ -695,10 +695,6 @@ "message": "$1 还没连接到任何网站。", "description": "$1 is the account name" }, - "connectedSnapSites": { - "message": "$1的snap已连接到这些站点。它们有上述的访问权限。", - "description": "$1 represents the name of the snap" - }, "connecting": { "message": "连接中……" }, @@ -1355,18 +1351,6 @@ "message": "文件导入失败?点击这里!", "description": "Helps user import their account from a JSON file" }, - "flaskSnapSettingsCardButtonCta": { - "message": "查看详细信息", - "description": "Call to action a user can take to see more information about the snap that is installed" - }, - "flaskSnapSettingsCardDateAddedOn": { - "message": "添加于", - "description": "Start of the sentence describing when and where snap was added" - }, - "flaskSnapSettingsCardFrom": { - "message": "自", - "description": "Part of the sentence describing when and where snap was added" - }, "flaskWelcomeUninstall": { "message": "您应该卸载此扩展程序", "description": "This request is shown on the Flask Welcome screen. It is intended for non-developers, and will be bolded." @@ -3227,10 +3211,6 @@ "settingsSearchMatchingNotFound": { "message": "没有找到匹配的结果." }, - "shorthandVersion": { - "message": "v$1", - "description": "$1 is replaced by a version string (e.g. 1.2.3)" - }, "show": { "message": "显示" }, @@ -3304,14 +3284,6 @@ "smartTransaction": { "message": "智能交易" }, - "snapAccess": { - "message": "$1的snap可以访问:", - "description": "$1 represents the name of the snap" - }, - "snapAdded": { - "message": "从 $2 添加到 $1", - "description": "$1 represents the date the snap was installed, $2 represents which origin installed the snap." - }, "snapContent": { "message": "此内容来自$1", "description": "This is shown when a snap shows transaction insight information in the confirmation UI. $1 is a link to the snap's settings page with the link text being the name of the snap." @@ -3348,9 +3320,6 @@ "snapsSettingsDescription": { "message": "管理您的Snap" }, - "snapsStatus": { - "message": "Snap状态取决于活动。" - }, "snapsToggle": { "message": "Snap仅在启用后才会运行" }, @@ -3951,9 +3920,6 @@ "thingsToKeep": { "message": "注意事项:" }, - "thisIsBasedOn": { - "message": "所根据的信息是来自" - }, "time": { "message": "时间" }, diff --git a/app/build-types/mmi/images/icons/stake.svg b/app/build-types/mmi/images/icons/stake.svg new file mode 100644 index 000000000..e6b1ce7c6 --- /dev/null +++ b/app/build-types/mmi/images/icons/stake.svg @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/images/icons/ban.svg b/app/images/icons/ban.svg new file mode 100644 index 000000000..dc73a3cf8 --- /dev/null +++ b/app/images/icons/ban.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/bold.svg b/app/images/icons/bold.svg new file mode 100644 index 000000000..0a0845a18 --- /dev/null +++ b/app/images/icons/bold.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/circle-x.svg b/app/images/icons/circle-x.svg new file mode 100644 index 000000000..4c30bbef7 --- /dev/null +++ b/app/images/icons/circle-x.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/download.svg b/app/images/icons/download.svg new file mode 100644 index 000000000..3831103eb --- /dev/null +++ b/app/images/icons/download.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/file.svg b/app/images/icons/file.svg new file mode 100644 index 000000000..58c71b139 --- /dev/null +++ b/app/images/icons/file.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/flask.svg b/app/images/icons/flask.svg new file mode 100644 index 000000000..51fc219fa --- /dev/null +++ b/app/images/icons/flask.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/plug.svg b/app/images/icons/plug.svg new file mode 100644 index 000000000..c92dd6f7a --- /dev/null +++ b/app/images/icons/plug.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/qr-code.svg b/app/images/icons/qr-code.svg new file mode 100644 index 000000000..af301c083 --- /dev/null +++ b/app/images/icons/qr-code.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/share.svg b/app/images/icons/share.svg new file mode 100644 index 000000000..13f424bc8 --- /dev/null +++ b/app/images/icons/share.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/square.svg b/app/images/icons/square.svg new file mode 100644 index 000000000..f39723e73 --- /dev/null +++ b/app/images/icons/square.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/tint.svg b/app/images/icons/tint.svg new file mode 100644 index 000000000..b4b91275c --- /dev/null +++ b/app/images/icons/tint.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/twitter.svg b/app/images/icons/twitter.svg new file mode 100644 index 000000000..137c6e3bb --- /dev/null +++ b/app/images/icons/twitter.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/upload.svg b/app/images/icons/upload.svg new file mode 100644 index 000000000..b1e2dbbe4 --- /dev/null +++ b/app/images/icons/upload.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/usb.svg b/app/images/icons/usb.svg new file mode 100644 index 000000000..850520fdd --- /dev/null +++ b/app/images/icons/usb.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/user-check.svg b/app/images/icons/user-check.svg new file mode 100644 index 000000000..4d694d231 --- /dev/null +++ b/app/images/icons/user-check.svg @@ -0,0 +1 @@ + diff --git a/app/images/icons/wifi.svg b/app/images/icons/wifi.svg new file mode 100644 index 000000000..8463fe5d8 --- /dev/null +++ b/app/images/icons/wifi.svg @@ -0,0 +1 @@ + diff --git a/app/scripts/background.js b/app/scripts/background.js index 048d494f8..808de08ec 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -18,11 +18,10 @@ import { ENVIRONMENT_TYPE_FULLSCREEN, EXTENSION_MESSAGES, PLATFORM_FIREFOX, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) MESSAGE_TYPE, ///: END:ONLY_INCLUDE_IN } from '../../shared/constants/app'; -import { SECOND } from '../../shared/constants/time'; import { REJECT_NOTIFICATION_CLOSE, REJECT_NOTIFICATION_CLOSE_SIG, @@ -33,6 +32,7 @@ import { import { checkForLastErrorAndLog } from '../../shared/modules/browser-runtime.utils'; import { isManifestV3 } from '../../shared/modules/mv3.utils'; import { maskObject } from '../../shared/modules/object.utils'; +import { getEnvironmentType, deferredPromise, getPlatform } from './lib/util'; import migrations from './migrations'; import Migrator from './lib/migrator'; import ExtensionPlatform from './platforms/extension'; @@ -51,12 +51,11 @@ import rawFirstTimeState from './first-time-state'; import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code'; import getObjStructure from './lib/getObjStructure'; import setupEnsIpfsResolver from './lib/ens-ipfs/setup'; -import { deferredPromise, getPlatform } from './lib/util'; /* eslint-enable import/first */ /* eslint-disable import/order */ -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(desktop) import { CONNECTION_TYPE_EXTERNAL, CONNECTION_TYPE_INTERNAL, @@ -85,6 +84,7 @@ let popupIsOpen = false; let notificationIsOpen = false; let uiIsTriggering = false; const openMetamaskTabsIDs = {}; +const openMetamaskConnections = new Map(); const requestAccountTabIds = {}; let controller; @@ -106,7 +106,7 @@ const PHISHING_WARNING_PAGE_TIMEOUT = ONE_SECOND_IN_MILLISECONDS; const ACK_KEEP_ALIVE_MESSAGE = 'ACK_KEEP_ALIVE_MESSAGE'; const WORKER_KEEP_ALIVE_MESSAGE = 'WORKER_KEEP_ALIVE_MESSAGE'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(desktop) const OVERRIDE_ORIGIN = { EXTENSION: 'EXTENSION', DESKTOP: 'DESKTOP_APP', @@ -185,10 +185,28 @@ let connectExternal; browser.runtime.onConnect.addListener(async (...args) => { // Queue up connection attempts here, waiting until after initialization await isInitialized; + const remotePort = args[0]; + const { sender } = remotePort; - // This is set in `setupController`, which is called as part of initialization - connectRemote(...args); + const url = sender?.url; + const detectedProcessName = url ? getEnvironmentType(url) : ''; + + const connectionId = generateConnectionId(remotePort, detectedProcessName); + const openConnections = openMetamaskConnections.get(connectionId) || 0; + + if ( + openConnections === 0 || + (detectedProcessName === 'background' && openConnections < 2) + // 2 background connections are allowed, one for phishing warning page and one for the ledger bridge keyring + ) { + // This is set in `setupController`, which is called as part of initialization + connectRemote(...args); + openMetamaskConnections.set(connectionId, openConnections + 1); + } else { + throw new Error('CONNECTION_ALREADY_EXISTS'); + } }); + browser.runtime.onConnectExternal.addListener(async (...args) => { // Queue up connection attempts here, waiting until after initialization await isInitialized; @@ -220,9 +238,9 @@ browser.runtime.onConnectExternal.addListener(async (...args) => { * @property {object} featureFlags - An object for optional feature flags. * @property {boolean} welcomeScreen - True if welcome screen should be shown. * @property {string} currentLocale - A locale string matching the user's preferred display language. - * @property {object} provider - The current selected network provider. - * @property {string} provider.rpcUrl - The address for the RPC API, if using an RPC API. - * @property {string} provider.type - An identifier for the type of network selected, allows MetaMask to use custom provider strategies for known networks. + * @property {object} providerConfig - The current selected network provider. + * @property {string} providerConfig.rpcUrl - The address for the RPC API, if using an RPC API. + * @property {string} providerConfig.type - An identifier for the type of network selected, allows MetaMask to use custom provider strategies for known networks. * @property {string} networkId - The stringified number of the current network ID. * @property {string} networkStatus - Either "unknown", "available", "unavailable", or "blocked", depending on the status of the currently selected network. * @property {object} accounts - An object mapping lower-case hex addresses to objects with "balance" and "address" keys, both storing hex string values. @@ -264,7 +282,7 @@ async function initialize() { const initState = await loadStateFromPersistence(); const initLangCode = await getFirstPreferredLangCode(); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) await DesktopManager.init(platform.getVersion()); ///: END:ONLY_INCLUDE_IN @@ -417,6 +435,21 @@ export async function loadStateFromPersistence() { return versionedData.data; } +function generateConnectionId(remotePort, detectedProcessName) { + const { sender } = remotePort; + const id = sender?.tab ? sender.tab.id : sender?.id; + if (!id || !detectedProcessName) { + console.error( + 'Must provide id and detectedProcessName to generate connection id.', + id, + detectedProcessName, + ); // eslint-disable-line no-console + throw new Error( + 'Must provide id and detectedProcessName to generate connection id.', + ); + } + return `${id}-${detectedProcessName}`; +} /** * Initializes the MetaMask Controller with any initial state and default language. * Configures platform-specific error reporting strategy. @@ -442,7 +475,6 @@ export function setupController( infuraProjectId: process.env.INFURA_PROJECT_ID, // User confirmation callbacks: showUserConfirmation: triggerUi, - openPopup, // initial state initState, // initial locale code @@ -464,7 +496,7 @@ export function setupController( setupEnsIpfsResolver({ getCurrentChainId: () => - controller.networkController.store.getState().provider.chainId, + controller.networkController.store.getState().providerConfig.chainId, getIpfsGateway: controller.preferencesController.getIpfsGateway.bind( controller.preferencesController, ), @@ -527,7 +559,7 @@ export function setupController( * @param {Port} remotePort - The port provided by a new context. */ connectRemote = async (remotePort) => { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) if ( DesktopManager.isDesktopEnabled() && OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.() @@ -572,7 +604,6 @@ export function setupController( // communication with popup controller.isClientOpen = true; controller.setupTrustedCommunication(portStream, remotePort.sender); - if (isManifestV3) { // If we get a WORKER_KEEP_ALIVE message, we respond with an ACK remotePort.onMessage.addListener((message) => { @@ -587,9 +618,11 @@ export function setupController( }); } + const connectionId = generateConnectionId(remotePort, processName); if (processName === ENVIRONMENT_TYPE_POPUP) { popupIsOpen = true; endOfStream(portStream, () => { + openMetamaskConnections.set(connectionId, 0); popupIsOpen = false; const isClientOpen = isClientOpenStatus(); controller.isClientOpen = isClientOpen; @@ -599,8 +632,8 @@ export function setupController( if (processName === ENVIRONMENT_TYPE_NOTIFICATION) { notificationIsOpen = true; - endOfStream(portStream, () => { + openMetamaskConnections.set(connectionId, 0); notificationIsOpen = false; const isClientOpen = isClientOpenStatus(); controller.isClientOpen = isClientOpen; @@ -616,6 +649,7 @@ export function setupController( openMetamaskTabsIDs[tabId] = true; endOfStream(portStream, () => { + openMetamaskConnections.set(connectionId, 0); delete openMetamaskTabsIDs[tabId]; const isClientOpen = isClientOpenStatus(); controller.isClientOpen = isClientOpen; @@ -653,7 +687,7 @@ export function setupController( // communication with page or other extension connectExternal = (remotePort) => { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) if ( DesktopManager.isDesktopEnabled() && OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.() @@ -684,7 +718,7 @@ export function setupController( METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, updateBadge, ); - controller.decryptMessageManager.on( + controller.decryptMessageController.hub.on( METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, updateBadge, ); @@ -727,14 +761,11 @@ export function setupController( } function getUnapprovedTransactionCount() { - const { unapprovedDecryptMsgCount } = controller.decryptMessageManager; const pendingApprovalCount = controller.approvalController.getTotalApprovalCount(); const waitingForUnlockCount = controller.appStateController.waitingForUnlock.length; - return ( - unapprovedDecryptMsgCount + pendingApprovalCount + waitingForUnlockCount - ); + return pendingApprovalCount + waitingForUnlockCount; } notificationManager.on( @@ -755,14 +786,9 @@ export function setupController( controller.txController.txStateManager.setTxStatusRejected(txId), ); controller.signController.rejectUnapproved(REJECT_NOTIFICATION_CLOSE_SIG); - controller.decryptMessageManager.messages - .filter((msg) => msg.status === 'unapproved') - .forEach((tx) => - controller.decryptMessageManager.rejectMsg( - tx.id, - REJECT_NOTIFICATION_CLOSE, - ), - ); + controller.decryptMessageController.rejectUnapproved( + REJECT_NOTIFICATION_CLOSE, + ); controller.encryptionPublicKeyController.rejectUnapproved( REJECT_NOTIFICATION_CLOSE, ); @@ -771,7 +797,7 @@ export function setupController( Object.values(controller.approvalController.state.pendingApprovals).forEach( ({ id, type }) => { switch (type) { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) case MESSAGE_TYPE.SNAP_DIALOG_ALERT: case MESSAGE_TYPE.SNAP_DIALOG_PROMPT: controller.approvalController.accept(id, null); @@ -793,7 +819,7 @@ export function setupController( updateBadge(); } - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) if (OVERRIDE_ORIGIN.DESKTOP !== overrides?.getOrigin?.()) { controller.store.subscribe((state) => { DesktopManager.setState(state); @@ -839,22 +865,6 @@ async function triggerUi() { } } -/** - * Opens the browser popup for user confirmation of watchAsset - * then it waits until user interact with the UI - */ -async function openPopup() { - await triggerUi(); - await new Promise((resolve) => { - const interval = setInterval(() => { - if (!notificationIsOpen) { - clearInterval(interval); - resolve(); - } - }, SECOND); - }); -} - // It adds the "App Installed" event into a queue of events, which will be tracked only after a user opts into metrics. const addAppInstalledEvent = () => { if (controller) { diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index cf61daff6..63eaf085d 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -46,6 +46,7 @@ export default class AppStateController extends EventEmitter { nftsDetectionNoticeDismissed: false, showTestnetMessageInDropdown: true, showBetaHeader: isBeta(), + showProductTour: true, trezorModel: null, currentPopupId: undefined, ...initState, @@ -331,6 +332,15 @@ export default class AppStateController extends EventEmitter { this.store.updateState({ showBetaHeader }); } + /** + * Sets whether the product tour should be shown + * + * @param showProductTour + */ + setShowProductTour(showProductTour) { + this.store.updateState({ showProductTour }); + } + /** * Sets a property indicating the model of the user's Trezor hardware wallet * diff --git a/app/scripts/controllers/decrypt-message.test.ts b/app/scripts/controllers/decrypt-message.test.ts new file mode 100644 index 000000000..032a15289 --- /dev/null +++ b/app/scripts/controllers/decrypt-message.test.ts @@ -0,0 +1,222 @@ +import { DecryptMessageManager } from '@metamask/message-manager'; +import { AbstractMessage } from '@metamask/message-manager/dist/AbstractMessageManager'; +import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics'; +import DecryptMessageController, { + DecryptMessageControllerMessenger, + DecryptMessageControllerOptions, + getDefaultState, +} from './decrypt-message'; + +const messageIdMock = '12345'; +const messageMock = { + metamaskId: messageIdMock, + time: 123, + status: 'unapproved', + type: 'testType', + rawSig: undefined, +} as any as AbstractMessage; + +const mockExtState = {}; + +jest.mock('@metamask/message-manager', () => ({ + DecryptMessageManager: jest.fn(), +})); + +const createKeyringControllerMock = () => ({ + decryptMessage: jest.fn(), +}); + +const createMessengerMock = () => + ({ + registerActionHandler: jest.fn(), + publish: jest.fn(), + call: jest.fn(), + } as any as jest.Mocked); + +const createDecryptMessageManagerMock = () => + ({ + getUnapprovedMessages: jest.fn(), + getUnapprovedMessagesCount: jest.fn(), + getMessage: jest.fn(), + addUnapprovedMessageAsync: jest.fn(), + approveMessage: jest.fn(), + setMessageStatusAndResult: jest.fn(), + rejectMessage: jest.fn(), + update: jest.fn(), + subscribe: jest.fn(), + updateMessage: jest.fn(), + updateMessageErrorInline: jest.fn(), + setResult: jest.fn(), + hub: { + on: jest.fn(), + }, + } as any as jest.Mocked); + +describe('EncryptionPublicKeyController', () => { + let decryptMessageController: DecryptMessageController; + + const decryptMessageManagerConstructorMock = + DecryptMessageManager as jest.MockedClass; + const getStateMock = jest.fn(); + const keyringControllerMock = createKeyringControllerMock(); + const messengerMock = createMessengerMock(); + const metricsEventMock = jest.fn(); + + const decryptMessageManagerMock = + createDecryptMessageManagerMock(); + + beforeEach(() => { + jest.resetAllMocks(); + + decryptMessageManagerConstructorMock.mockReturnValue( + decryptMessageManagerMock, + ); + + decryptMessageController = new DecryptMessageController({ + getState: getStateMock as any, + keyringController: keyringControllerMock as any, + messenger: messengerMock as any, + metricsEvent: metricsEventMock as any, + } as DecryptMessageControllerOptions); + }); + + it('should return unapprovedMsgCount', () => { + decryptMessageManagerMock.getUnapprovedMessagesCount.mockReturnValue(5); + expect(decryptMessageController.unapprovedDecryptMsgCount).toBe(5); + }); + + it('should reset state', () => { + decryptMessageController.update(() => ({ + unapprovedDecryptMsgs: { + [messageIdMock]: messageMock, + } as any, + unapprovedDecryptMsgCount: 1, + })); + decryptMessageController.resetState(); + expect(decryptMessageController.state).toStrictEqual(getDefaultState()); + }); + + it('should clear unapproved messages', () => { + decryptMessageController.clearUnapproved(); + expect(decryptMessageController.state).toStrictEqual(getDefaultState()); + expect(decryptMessageManagerMock.update).toBeCalledTimes(1); + }); + it('should add unapproved messages', async () => { + await decryptMessageController.newRequestDecryptMessage(messageMock); + + expect(decryptMessageManagerMock.addUnapprovedMessageAsync).toBeCalledTimes( + 1, + ); + expect(decryptMessageManagerMock.addUnapprovedMessageAsync).toBeCalledWith( + messageMock, + undefined, + ); + }); + + it('should decrypt message', async () => { + const messageToDecrypt = { + ...messageMock, + data: '0x7b22666f6f223a22626172227d', + }; + decryptMessageManagerMock.approveMessage.mockResolvedValue( + messageToDecrypt, + ); + keyringControllerMock.decryptMessage.mockResolvedValue('decryptedMessage'); + getStateMock.mockReturnValue(mockExtState); + + const result = await decryptMessageController.decryptMessage( + messageToDecrypt, + ); + + expect(decryptMessageManagerMock.approveMessage).toBeCalledTimes(1); + expect(decryptMessageManagerMock.approveMessage).toBeCalledWith( + messageToDecrypt, + ); + expect(keyringControllerMock.decryptMessage).toBeCalledTimes(1); + expect(keyringControllerMock.decryptMessage).toBeCalledWith( + messageToDecrypt, + ); + expect(decryptMessageManagerMock.setMessageStatusAndResult).toBeCalledTimes( + 1, + ); + expect(decryptMessageManagerMock.setMessageStatusAndResult).toBeCalledWith( + messageIdMock, + 'decryptedMessage', + 'decrypted', + ); + expect(result).toBe(mockExtState); + }); + + it('should cancel decrypt request', async () => { + const messageToDecrypt = { + ...messageMock, + data: '0x7b22666f6f223a22626172227d', + }; + decryptMessageManagerMock.approveMessage.mockResolvedValue( + messageToDecrypt, + ); + keyringControllerMock.decryptMessage.mockRejectedValue(new Error('error')); + getStateMock.mockReturnValue(mockExtState); + + return expect( + decryptMessageController.decryptMessage(messageToDecrypt), + ).rejects.toThrow('error'); + }); + + it('should decrypt message inline', async () => { + const messageToDecrypt = { + ...messageMock, + data: '0x7b22666f6f223a22626172227d', + }; + decryptMessageManagerMock.getMessage.mockReturnValue(messageToDecrypt); + keyringControllerMock.decryptMessage.mockResolvedValue('decryptedMessage'); + getStateMock.mockReturnValue(mockExtState); + + const result = await decryptMessageController.decryptMessageInline( + messageToDecrypt, + ); + + expect(decryptMessageManagerMock.setResult).toBeCalledTimes(1); + expect(decryptMessageManagerMock.setResult).toBeCalledWith( + messageMock.metamaskId, + 'decryptedMessage', + ); + expect(result).toBe(mockExtState); + }); + + it('should be able to cancel decrypt message', async () => { + decryptMessageManagerMock.rejectMessage.mockResolvedValue(messageMock); + getStateMock.mockReturnValue(mockExtState); + + const result = await decryptMessageController.cancelDecryptMessage( + messageIdMock, + ); + + expect(decryptMessageManagerMock.rejectMessage).toBeCalledTimes(1); + expect(decryptMessageManagerMock.rejectMessage).toBeCalledWith( + messageIdMock, + ); + expect(result).toBe(mockExtState); + }); + + it('should be able to reject all unapproved messages', async () => { + decryptMessageManagerMock.getUnapprovedMessages.mockReturnValue({ + [messageIdMock]: messageMock, + }); + + await decryptMessageController.rejectUnapproved('reason to cancel'); + + expect(decryptMessageManagerMock.rejectMessage).toBeCalledTimes(1); + expect(decryptMessageManagerMock.rejectMessage).toBeCalledWith( + messageIdMock, + ); + expect(metricsEventMock).toBeCalledTimes(1); + expect(metricsEventMock).toBeCalledWith({ + event: 'reason to cancel', + category: MetaMetricsEventCategory.Messages, + properties: { + action: 'Decrypt Message Request', + }, + }); + }); +}); diff --git a/app/scripts/controllers/decrypt-message.ts b/app/scripts/controllers/decrypt-message.ts new file mode 100644 index 000000000..779b22f78 --- /dev/null +++ b/app/scripts/controllers/decrypt-message.ts @@ -0,0 +1,394 @@ +import EventEmitter from 'events'; +import log from 'loglevel'; +import { + DecryptMessageManager, + DecryptMessageParams, + DecryptMessageParamsMetamask, +} from '@metamask/message-manager'; +import { KeyringController } from '@metamask/eth-keyring-controller'; +import { + AbstractMessage, + AbstractMessageManager, + AbstractMessageParams, + AbstractMessageParamsMetamask, + MessageManagerState, + OriginalRequest, +} from '@metamask/message-manager/dist/AbstractMessageManager'; +import { + BaseControllerV2, + RestrictedControllerMessenger, +} from '@metamask/base-controller'; +import { + AcceptRequest, + AddApprovalRequest, + RejectRequest, +} from '@metamask/approval-controller'; +import { ApprovalType, ORIGIN_METAMASK } from '@metamask/controller-utils'; +import { Patch } from 'immer'; +import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics'; +import { stripHexPrefix } from '../../../shared/modules/hexstring-utils'; + +const controllerName = 'DecryptMessageController'; + +const stateMetadata = { + unapprovedDecryptMsgs: { persist: false, anonymous: false }, + unapprovedDecryptMsgCount: { persist: false, anonymous: false }, +}; + +export const getDefaultState = () => ({ + unapprovedDecryptMsgs: {}, + unapprovedDecryptMsgCount: 0, +}); + +export type CoreMessage = AbstractMessage & { + messageParams: AbstractMessageParams; +}; + +export type StateMessage = Required< + Omit +>; + +export type DecryptMessageControllerState = { + unapprovedDecryptMsgs: Record; + unapprovedDecryptMsgCount: number; +}; + +export type GetDecryptMessageState = { + type: `${typeof controllerName}:getState`; + handler: () => DecryptMessageControllerState; +}; + +export type DecryptMessageStateChange = { + type: `${typeof controllerName}:stateChange`; + payload: [DecryptMessageControllerState, Patch[]]; +}; + +export type DecryptMessageControllerActions = GetDecryptMessageState; + +export type DecryptMessageControllerEvents = DecryptMessageStateChange; + +type AllowedActions = AddApprovalRequest | AcceptRequest | RejectRequest; + +export type DecryptMessageControllerMessenger = RestrictedControllerMessenger< + typeof controllerName, + DecryptMessageControllerActions | AllowedActions, + DecryptMessageControllerEvents, + AllowedActions['type'], + never +>; + +export type DecryptMessageControllerOptions = { + getState: () => any; + keyringController: KeyringController; + messenger: DecryptMessageControllerMessenger; + metricsEvent: (payload: any, options?: any) => void; +}; + +/** + * Controller for decrypt signing requests requiring user approval. + */ +export default class DecryptMessageController extends BaseControllerV2< + typeof controllerName, + DecryptMessageControllerState, + DecryptMessageControllerMessenger +> { + hub: EventEmitter; + + private _getState: () => any; + + private _keyringController: KeyringController; + + private _metricsEvent: (payload: any, options?: any) => void; + + private _decryptMessageManager: DecryptMessageManager; + + /** + * Construct a DecryptMessage controller. + * + * @param options - The controller options. + * @param options.getState - Callback to retrieve all user state. + * @param options.keyringController - An instance of a keyring controller used to decrypt message + * @param options.messenger - A reference to the messaging system. + * @param options.metricsEvent - A function for emitting a metric event. + */ + constructor({ + getState, + keyringController, + metricsEvent, + messenger, + }: DecryptMessageControllerOptions) { + super({ + metadata: stateMetadata, + messenger, + name: controllerName, + state: getDefaultState(), + }); + this._getState = getState; + this._keyringController = keyringController; + this._metricsEvent = metricsEvent; + + this.hub = new EventEmitter(); + + this._decryptMessageManager = new DecryptMessageManager( + undefined, + undefined, + undefined, + ['decrypted'], + ); + + this._decryptMessageManager.hub.on('updateBadge', () => { + this.hub.emit('updateBadge'); + }); + + this._decryptMessageManager.hub.on( + 'unapprovedMessage', + (messageParams: AbstractMessageParamsMetamask) => { + this._requestApproval(messageParams); + }, + ); + + this._subscribeToMessageState( + this._decryptMessageManager, + (state, newMessages, messageCount) => { + state.unapprovedDecryptMsgs = newMessages; + state.unapprovedDecryptMsgCount = messageCount; + }, + ); + } + + /** + * A getter for the number of 'unapproved' Messages in the DecryptMessageManager. + * + * @returns The number of 'unapproved' Messages in the DecryptMessageManager. + */ + get unapprovedDecryptMsgCount(): number { + return this._decryptMessageManager.getUnapprovedMessagesCount(); + } + + /** + * Reset the controller state to the initial state. + */ + resetState() { + this.update(() => getDefaultState()); + } + + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this._decryptMessageManager.update({ + unapprovedMessages: {}, + unapprovedMessagesCount: 0, + }); + } + + /** + * Called when a dapp uses the eth_decrypt method + * + * @param messageParams - The params passed to eth_decrypt. + * @param req - The original request, containing the origin. + * @returns Promise resolving to the raw data of the signature request. + */ + async newRequestDecryptMessage( + messageParams: DecryptMessageParams, + req: OriginalRequest, + ): Promise { + return this._decryptMessageManager.addUnapprovedMessageAsync( + messageParams, + req, + ); + } + + /** + * Signifies a user's approval to decrypt a message in queue. + * Triggers decrypt, and the callback function from newUnsignedDecryptMessage. + * + * @param messageParams - The params of the message to decrypt & return to the Dapp. + * @returns A full state update. + */ + async decryptMessage(messageParams: DecryptMessageParamsMetamask) { + const messageId = messageParams.metamaskId as string; + try { + const cleanMessageParams = + await this._decryptMessageManager.approveMessage(messageParams); + + cleanMessageParams.data = this._parseMessageData(cleanMessageParams.data); + const rawMessage = await this._keyringController.decryptMessage( + cleanMessageParams, + ); + + this._decryptMessageManager.setMessageStatusAndResult( + messageId, + rawMessage, + 'decrypted', + ); + this._acceptApproval(messageId); + } catch (error) { + log.info('MetaMaskController - eth_decrypt failed.', error); + this._cancelAbstractMessage(this._decryptMessageManager, messageId); + throw error; + } + return this._getState(); + } + + /** + * Only decrypt message and don't touch transaction state + * + * @param messageParams - The params of the message to decrypt. + * @returns A full state update. + */ + async decryptMessageInline(messageParams: DecryptMessageParamsMetamask) { + const messageId = messageParams.metamaskId as string; + messageParams.data = this._parseMessageData(messageParams.data); + const rawMessage = await this._keyringController.decryptMessage( + messageParams, + ); + + this._decryptMessageManager.setResult(messageId, rawMessage); + + return this._getState(); + } + + /** + * Used to cancel a eth_decrypt type message. + * + * @param messageId - The ID of the message to cancel. + * @returns A full state update. + */ + cancelDecryptMessage(messageId: string) { + this._decryptMessageManager.rejectMessage(messageId); + this._rejectApproval(messageId); + return this._getState(); + } + + /** + * Reject all unapproved messages of any type. + * + * @param reason - A message to indicate why. + */ + rejectUnapproved(reason?: string) { + Object.keys(this._decryptMessageManager.getUnapprovedMessages()).forEach( + (messageId) => { + this._cancelAbstractMessage( + this._decryptMessageManager, + messageId, + reason, + ); + }, + ); + } + + private _acceptApproval(messageId: string) { + this.messagingSystem.call('ApprovalController:acceptRequest', messageId); + } + + private _cancelAbstractMessage( + messageManager: AbstractMessageManager< + AbstractMessage, + AbstractMessageParams, + AbstractMessageParamsMetamask + >, + messageId: string, + reason?: string, + ) { + if (reason) { + this._metricsEvent({ + event: reason, + category: MetaMetricsEventCategory.Messages, + properties: { + action: 'Decrypt Message Request', + }, + }); + } + + messageManager.rejectMessage(messageId); + this._rejectApproval(messageId); + + return this._getState(); + } + + private _subscribeToMessageState( + messageManager: AbstractMessageManager< + AbstractMessage, + AbstractMessageParams, + AbstractMessageParamsMetamask + >, + updateState: ( + state: DecryptMessageControllerState, + newMessages: Record, + messageCount: number, + ) => void, + ) { + messageManager.subscribe((state: MessageManagerState) => { + const newMessages = this._migrateMessages( + state.unapprovedMessages as any, + ); + this.update((draftState) => { + updateState(draftState, newMessages, state.unapprovedMessagesCount); + }); + }); + } + + private _migrateMessages( + coreMessages: Record, + ): Record { + const stateMessages: Record = {}; + + for (const messageId of Object.keys(coreMessages)) { + const coreMessage = coreMessages[messageId]; + const stateMessage = this._migrateMessage(coreMessage); + stateMessages[messageId] = stateMessage; + } + + return stateMessages; + } + + private _migrateMessage(coreMessage: CoreMessage): StateMessage { + const { messageParams, ...coreMessageData } = coreMessage; + + const stateMessage = { + ...coreMessageData, + rawSig: coreMessage.rawSig as string, + msgParams: messageParams, + origin: messageParams.origin, + }; + + return stateMessage; + } + + private _requestApproval(messageParams: AbstractMessageParamsMetamask) { + const id = messageParams.metamaskId as string; + const origin = messageParams.origin || ORIGIN_METAMASK; + try { + this.messagingSystem.call( + 'ApprovalController:addRequest', + { + id, + origin, + type: ApprovalType.EthDecrypt, + }, + true, + ); + } catch (error) { + log.info('Error adding request to approval controller', error); + } + } + + private _parseMessageData(data: string) { + const stripped = stripHexPrefix(data); + const buff = Buffer.from(stripped, 'hex'); + return JSON.parse(buff.toString('utf8')); + } + + private _rejectApproval(messageId: string) { + try { + this.messagingSystem.call( + 'ApprovalController:rejectRequest', + messageId, + 'Cancel', + ); + } catch (error) { + log.info('Error rejecting request to approval controller', error); + } + } +} diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 2b23dd71b..33e765f91 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -209,7 +209,7 @@ export default class DetectTokensController { } getChainIdFromNetworkStore(network) { - return network?.store.getState().provider.chainId; + return network?.store.getState().providerConfig.chainId; } /* eslint-disable accessor-pairs */ diff --git a/app/scripts/controllers/detect-tokens.test.js b/app/scripts/controllers/detect-tokens.test.js index d5f6eb7bd..8e7bddd28 100644 --- a/app/scripts/controllers/detect-tokens.test.js +++ b/app/scripts/controllers/detect-tokens.test.js @@ -235,7 +235,7 @@ describe('DetectTokensController', function () { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, + ...networkState.providerConfig, }, }; return cb(modifiedNetworkState); @@ -254,8 +254,10 @@ describe('DetectTokensController', function () { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: convertHexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: convertHexToDecimal( + networkState.providerConfig.chainId, + ), }, }; return cb(modifiedNetworkState); diff --git a/app/scripts/controllers/encryption-public-key.ts b/app/scripts/controllers/encryption-public-key.ts index de710c501..4ea2c1afe 100644 --- a/app/scripts/controllers/encryption-public-key.ts +++ b/app/scripts/controllers/encryption-public-key.ts @@ -342,36 +342,31 @@ export default class EncryptionPublicKeyController extends BaseControllerV2< messageCount: number, ) => void, ) { - messageManager.subscribe( - async (state: MessageManagerState) => { - const newMessages = await this._migrateMessages( - state.unapprovedMessages as any, - ); - this.update((draftState) => { - updateState(draftState, newMessages, state.unapprovedMessagesCount); - }); - }, - ); + messageManager.subscribe((state: MessageManagerState) => { + const newMessages = this._migrateMessages( + state.unapprovedMessages as any, + ); + this.update((draftState) => { + updateState(draftState, newMessages, state.unapprovedMessagesCount); + }); + }); } - private async _migrateMessages( + private _migrateMessages( coreMessages: Record, - ): Promise> { + ): Record { const stateMessages: Record = {}; for (const messageId of Object.keys(coreMessages)) { const coreMessage = coreMessages[messageId]; - const stateMessage = await this._migrateMessage(coreMessage); - + const stateMessage = this._migrateMessage(coreMessage); stateMessages[messageId] = stateMessage; } return stateMessages; } - private async _migrateMessage( - coreMessage: CoreMessage, - ): Promise { + private _migrateMessage(coreMessage: CoreMessage): StateMessage { const { messageParams, ...coreMessageData } = coreMessage; // Core message managers use messageParams but frontend uses msgParams with lots of references diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index c433b3f5e..23f74b21d 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -724,7 +724,7 @@ export default class MetaMetricsController { [MetaMetricsUserTrait.Theme]: metamaskState.theme || 'default', [MetaMetricsUserTrait.TokenDetectionEnabled]: metamaskState.useTokenDetection, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) [MetaMetricsUserTrait.DesktopEnabled]: metamaskState.desktopEnabled || false, ///: END:ONLY_INCLUDE_IN diff --git a/app/scripts/controllers/metametrics.test.js b/app/scripts/controllers/metametrics.test.js index dbd0e56c8..9e2a415e8 100644 --- a/app/scripts/controllers/metametrics.test.js +++ b/app/scripts/controllers/metametrics.test.js @@ -65,7 +65,7 @@ const DEFAULT_PAGE_PROPERTIES = { function getMockNetworkController() { let state = { - provider: { + providerConfig: { type: NETWORK_TYPES.GOERLI, chainId: FAKE_CHAIN_ID, }, @@ -134,7 +134,7 @@ function getMetaMetricsController({ return new MetaMetricsController({ segment: segmentInstance || segment, getCurrentChainId: () => - networkController.store.getState().provider.chainId, + networkController.store.getState().providerConfig.chainId, onNetworkDidChange: networkController.onNetworkDidChange.bind(networkController), preferencesStore, @@ -203,7 +203,7 @@ describe('MetaMetricsController', function () { networkController, }); networkController.store.updateState({ - provider: { + providerConfig: { type: 'NEW_NETWORK', chainId: '0xaab', }, diff --git a/app/scripts/controllers/network/network-controller.test.ts b/app/scripts/controllers/network/network-controller.test.ts index c3360c140..2099e427e 100644 --- a/app/scripts/controllers/network/network-controller.test.ts +++ b/app/scripts/controllers/network/network-controller.test.ts @@ -164,7 +164,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'http://example-custom-rpc.metamask.io', chainId: '0x9999' as const, @@ -188,7 +188,7 @@ describe('NetworkController', () => { }, "networkId": null, "networkStatus": "unknown", - "provider": { + "providerConfig": { "chainId": "0x9999", "nickname": "Test initial state", "rpcUrl": "http://example-custom-rpc.metamask.io", @@ -212,7 +212,7 @@ describe('NetworkController', () => { }, "networkId": null, "networkStatus": "unknown", - "provider": { + "providerConfig": { "chainId": "0x539", "nickname": "Localhost 8545", "rpcUrl": "http://localhost:8545", @@ -227,11 +227,9 @@ describe('NetworkController', () => { describe('destroy', () => { it('does not throw if called before the provider is initialized', async () => { - const controller = new NetworkController( - buildDefaultNetworkControllerOptions(), - ); - - expect(await controller.destroy()).toBeUndefined(); + await withController(async ({ controller }) => { + expect(await controller.destroy()).toBeUndefined(); + }); }); it('stops the block tracker for the currently selected network as long as the provider has been initialized', async () => { @@ -262,7 +260,7 @@ describe('NetworkController', () => { /* @ts-expect-error We're intentionally passing bad input. */ { state: { - provider: invalidProviderConfig, + providerConfig: invalidProviderConfig, }, }, async ({ controller }) => { @@ -281,7 +279,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -328,14 +326,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked or infuraIsUnblocked, depending on whether Infura is blocking requests', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -343,13 +337,13 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.initializeProvider(); @@ -365,7 +359,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -405,7 +399,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -450,7 +444,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', chainId: '0x1337', rpcUrl: 'https://mock-rpc-url', @@ -505,14 +499,10 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -528,13 +518,13 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.initializeProvider(); @@ -547,14 +537,10 @@ describe('NetworkController', () => { }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -570,13 +556,13 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, count: 0, operation: async () => { @@ -593,7 +579,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -639,7 +625,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -719,7 +705,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -802,7 +788,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'goerli', // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1102,7 +1088,7 @@ describe('NetworkController', () => { nickname: 'Test initial state', }; const initialState = { - provider: providerConfig, + providerConfig, networkDetails: { EIPS: { 1559: true, @@ -1130,53 +1116,41 @@ describe('NetworkController', () => { }); it('does not emit infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider(); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - await withController( - { messenger: restrictedMessenger }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider(); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.InfuraIsUnblocked, + count: 0, + operation: async () => { + await controller.lookupNetwork(); + }, + }); - const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.InfuraIsUnblocked, - count: 0, - operation: async () => { - await controller.lookupNetwork(); - }, - }); - - expect(await promiseForNoInfuraIsUnblockedEvents).toBeTruthy(); - }, - ); + expect(await promiseForNoInfuraIsUnblockedEvents).toBeTruthy(); + }); }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider(); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - await withController( - { messenger: restrictedMessenger }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider(); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.InfuraIsBlocked, + count: 0, + operation: async () => { + await controller.lookupNetwork(); + }, + }); - const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.InfuraIsBlocked, - count: 0, - operation: async () => { - await controller.lookupNetwork(); - }, - }); - - expect(await promiseForNoInfuraIsBlockedEvents).toBeTruthy(); - }, - ); + expect(await promiseForNoInfuraIsBlockedEvents).toBeTruthy(); + }); }); }); @@ -1186,7 +1160,7 @@ describe('NetworkController', () => { /* @ts-expect-error We are intentionally not including a chainId in the provider config. */ { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'http://example-custom-rpc.metamask.io', }, @@ -1214,28 +1188,24 @@ describe('NetworkController', () => { }); it('does not emit infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( /* @ts-expect-error We are intentionally not including a chainId in the provider config. */ { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'http://example-custom-rpc.metamask.io', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); await controller.initializeProvider(); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, operation: async () => { @@ -1249,28 +1219,24 @@ describe('NetworkController', () => { }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( /* @ts-expect-error We are intentionally not including a chainId in the provider config. */ { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'http://example-custom-rpc.metamask.io', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); await controller.initializeProvider(); const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, count: 0, operation: async () => { @@ -1291,7 +1257,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1339,7 +1305,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1385,7 +1351,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1435,7 +1401,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1482,14 +1448,10 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -1497,7 +1459,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -1518,7 +1480,7 @@ describe('NetworkController', () => { }); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.lookupNetwork(); @@ -1536,7 +1498,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -1581,7 +1543,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1647,7 +1609,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1698,14 +1660,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -1713,7 +1671,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -1732,7 +1690,7 @@ describe('NetworkController', () => { }); const infuraIsBlocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, operation: async () => { await controller.lookupNetwork(); @@ -1745,14 +1703,10 @@ describe('NetworkController', () => { }); it('does not emit infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -1760,7 +1714,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -1780,7 +1734,7 @@ describe('NetworkController', () => { const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, operation: async () => { @@ -1799,7 +1753,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1870,7 +1824,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -1941,7 +1895,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2010,7 +1964,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2067,63 +2021,42 @@ describe('NetworkController', () => { }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - - await withController( - { - messenger: restrictedMessenger, - state: { - provider: { - type: networkType, - // NOTE: This doesn't need to match the logical chain ID of - // the network selected, it just needs to exist - chainId: '0x9999999', + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider([ + { + request: { + method: 'eth_getBlockByNumber', }, + error: GENERIC_JSON_RPC_ERROR, }, - }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider([ - { - request: { - method: 'eth_getBlockByNumber', - }, - error: GENERIC_JSON_RPC_ERROR, - }, - ]); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - await withoutCallingLookupNetwork({ - controller, - operation: async () => { - await controller.initializeProvider(); - }, - }); + ]); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + await withoutCallingLookupNetwork({ + controller, + operation: async () => { + await controller.initializeProvider(); + }, + }); - const promiseForNoInfuraIsBlockedEvents = - waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.InfuraIsBlocked, - count: 0, - operation: async () => { - await controller.lookupNetwork(); - }, - }); + const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.InfuraIsBlocked, + count: 0, + operation: async () => { + await controller.lookupNetwork(); + }, + }); - expect(await promiseForNoInfuraIsBlockedEvents).toBeTruthy(); - }, - ); + expect(await promiseForNoInfuraIsBlockedEvents).toBeTruthy(); + }); }); it('does not emit infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2131,7 +2064,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -2151,7 +2084,7 @@ describe('NetworkController', () => { const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, operation: async () => { @@ -2170,7 +2103,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2280,7 +2213,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2372,7 +2305,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -2471,14 +2404,10 @@ describe('NetworkController', () => { ); } - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -2487,7 +2416,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [ buildFakeProvider([ { @@ -2536,12 +2465,12 @@ describe('NetworkController', () => { }); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, }); const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, }); @@ -2562,7 +2491,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2613,7 +2542,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2666,7 +2595,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2718,7 +2647,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2767,21 +2696,17 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -2808,7 +2733,7 @@ describe('NetworkController', () => { }); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.lookupNetwork(); @@ -2826,7 +2751,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2892,7 +2817,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -2956,7 +2881,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3020,7 +2945,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3098,21 +3023,17 @@ describe('NetworkController', () => { }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -3137,7 +3058,7 @@ describe('NetworkController', () => { }); const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, count: 0, operation: async () => { @@ -3151,21 +3072,17 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -3190,7 +3107,7 @@ describe('NetworkController', () => { }); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.lookupNetwork(); @@ -3208,7 +3125,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3272,7 +3189,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3338,7 +3255,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3410,21 +3327,17 @@ describe('NetworkController', () => { }); it('does not emit infuraIsBlocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -3449,7 +3362,7 @@ describe('NetworkController', () => { }); const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, count: 0, operation: async () => { @@ -3463,21 +3376,17 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -3502,7 +3411,7 @@ describe('NetworkController', () => { }); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.lookupNetwork(); @@ -3520,7 +3429,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3612,7 +3521,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3716,7 +3625,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3833,14 +3742,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked, not infuraIsUnblocked, if the second network is blocked, even if the first one is not', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -3849,7 +3754,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [ buildFakeProvider([ { @@ -3908,12 +3813,12 @@ describe('NetworkController', () => { }); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, }); const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, }); @@ -3931,7 +3836,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -4027,7 +3932,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -4130,7 +4035,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -4247,14 +4152,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked, not infuraIsUnblocked, if the second network is blocked, even if the first one is not', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -4263,7 +4164,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [ buildFakeProvider([ { @@ -4322,12 +4223,12 @@ describe('NetworkController', () => { }); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, }); const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, }); @@ -4377,7 +4278,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url-1', chainId: '0x111', @@ -4414,7 +4315,7 @@ describe('NetworkController', () => { await controller.setActiveNetwork('testNetworkConfiguration'); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ id: 'testNetworkConfiguration', type: 'rpc', rpcUrl: 'https://mock-rpc-url-2', @@ -4430,14 +4331,10 @@ describe('NetworkController', () => { }); it('emits networkWillChange before making any changes to the network status', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url-1', chainId: '0x111', @@ -4453,7 +4350,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [ buildFakeProvider([ { @@ -4500,7 +4397,7 @@ describe('NetworkController', () => { expect(initialNetworkStatus).toBe('available'); const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkWillChange, operation: () => { // Intentionally not awaited because we're checking state @@ -4522,7 +4419,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url-1', chainId: '0x111', @@ -4600,7 +4497,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url-1', chainId: '0x111', @@ -4746,7 +4643,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url-1', chainId: '0x111', @@ -4795,12 +4692,8 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { networkConfigurations: { testNetworkConfiguration: { @@ -4812,7 +4705,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient() @@ -4824,7 +4717,7 @@ describe('NetworkController', () => { .mockReturnValue(fakeNetworkClient); const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkDidChange, operation: async () => { await controller.setActiveNetwork('testNetworkConfiguration'); @@ -4837,12 +4730,8 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { networkConfigurations: { testNetworkConfiguration: { @@ -4854,7 +4743,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient() @@ -4866,7 +4755,7 @@ describe('NetworkController', () => { .mockReturnValue(fakeNetworkClient); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.setActiveNetwork('testNetworkConfiguration'); @@ -4985,7 +4874,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5004,7 +4893,7 @@ describe('NetworkController', () => { controller.setProviderType(networkType); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ type: networkType, rpcUrl: undefined, chainId, @@ -5017,36 +4906,30 @@ describe('NetworkController', () => { }); it('emits networkWillChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider(); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - await withController( - { messenger: restrictedMessenger }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider(); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + const networkWillChange = await waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.NetworkWillChange, + operation: () => { + // Intentionally not awaited because we're capturing an event + // emitted partway through the operation + controller.setProviderType(networkType); + }, + }); - const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.NetworkWillChange, - operation: () => { - // Intentionally not awaited because we're capturing an event - // emitted partway through the operation - controller.setProviderType(networkType); - }, - }); - - expect(networkWillChange).toBeTruthy(); - }, - ); + expect(networkWillChange).toBeTruthy(); + }); }); it('resets the network status to "unknown" before emitting networkDidChange', async () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5114,7 +4997,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5244,7 +5127,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5286,63 +5169,50 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider(); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - await withController( - { messenger: restrictedMessenger }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider(); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + const networkDidChange = await waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.NetworkDidChange, + operation: async () => { + await controller.setProviderType(networkType); + }, + }); - const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.NetworkDidChange, - operation: async () => { - await controller.setProviderType(networkType); - }, - }); - - expect(networkDidChange).toBeTruthy(); - }, - ); + expect(networkDidChange).toBeTruthy(); + }); }); it('emits infuraIsBlocked or infuraIsUnblocked, depending on whether Infura is blocking requests', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - - await withController( - { messenger: restrictedMessenger }, - async ({ controller }) => { - const fakeProvider = buildFakeProvider([ - { - request: { - method: 'eth_getBlockByNumber', - }, - error: BLOCKED_INFURA_JSON_RPC_ERROR, + await withController(async ({ controller, messenger }) => { + const fakeProvider = buildFakeProvider([ + { + request: { + method: 'eth_getBlockByNumber', }, - ]); - const fakeNetworkClient = buildFakeClient(fakeProvider); - mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); - const promiseForNoInfuraIsUnblockedEvents = - waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.InfuraIsUnblocked, - count: 0, - }); - const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, - eventType: NetworkControllerEventType.InfuraIsBlocked, - }); + error: BLOCKED_INFURA_JSON_RPC_ERROR, + }, + ]); + const fakeNetworkClient = buildFakeClient(fakeProvider); + mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); + const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.InfuraIsUnblocked, + count: 0, + }); + const promiseForInfuraIsBlocked = waitForPublishedEvents({ + messenger, + eventType: NetworkControllerEventType.InfuraIsBlocked, + }); - await controller.setProviderType(networkType); + await controller.setProviderType(networkType); - expect(await promiseForNoInfuraIsUnblockedEvents).toBeTruthy(); - expect(await promiseForInfuraIsBlocked).toBeTruthy(); - }, - ); + expect(await promiseForNoInfuraIsUnblockedEvents).toBeTruthy(); + expect(await promiseForInfuraIsBlocked).toBeTruthy(); + }); }); it('determines the status of the network, storing it in state', async () => { @@ -5436,14 +5306,10 @@ describe('NetworkController', () => { for (const { networkType } of INFURA_NETWORKS) { describe(`when the type in the provider configuration is "${networkType}"`, () => { it('emits networkWillChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5451,13 +5317,13 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkWillChange, operation: () => { // Intentionally not awaited because we want to capture an @@ -5475,7 +5341,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5521,7 +5387,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5575,7 +5441,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5618,7 +5484,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5644,14 +5510,10 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5659,13 +5521,13 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkDidChange, operation: async () => { await controller.resetConnection(); @@ -5678,14 +5540,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked or infuraIsUnblocked, depending on whether Infura is blocking requests', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5693,7 +5551,7 @@ describe('NetworkController', () => { }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider([ { request: { @@ -5706,12 +5564,12 @@ describe('NetworkController', () => { mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, }); const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, }); @@ -5727,7 +5585,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5766,7 +5624,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -5807,27 +5665,23 @@ describe('NetworkController', () => { describe(`when the type in the provider configuration is "rpc"`, () => { it('emits networkWillChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkWillChange, operation: () => { // Intentionally not awaited because we're capturing an event @@ -5845,7 +5699,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5888,7 +5742,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5945,7 +5799,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -5987,7 +5841,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -6012,27 +5866,23 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkDidChange, operation: async () => { await controller.resetConnection(); @@ -6045,27 +5895,23 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', }, }, }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProvider = buildFakeProvider(); const fakeNetworkClient = buildFakeClient(fakeProvider); mockCreateNetworkClient().mockReturnValue(fakeNetworkClient); const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.resetConnection(); @@ -6081,7 +5927,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -6117,7 +5963,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -6162,7 +6008,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID // of the network selected, it just needs to exist @@ -6211,7 +6057,7 @@ describe('NetworkController', () => { }) .mockReturnValue(fakeNetworkClients[1]); await controller.setActiveNetwork('testNetworkConfiguration'); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ type: 'rpc', id: 'testNetworkConfiguration', rpcUrl: 'https://mock-rpc-url-2', @@ -6230,7 +6076,7 @@ describe('NetworkController', () => { }, }); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ type: networkType, chainId: '0x111', rpcUrl: 'https://mock-rpc-url-1', @@ -6245,14 +6091,10 @@ describe('NetworkController', () => { }); it('emits networkWillChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6269,7 +6111,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [buildFakeProvider(), buildFakeProvider()]; const fakeNetworkClients = [ buildFakeClient(fakeProviders[0]), @@ -6294,7 +6136,7 @@ describe('NetworkController', () => { controller, operation: async () => { const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkWillChange, operation: async () => { await controller.rollbackToPreviousProvider(); @@ -6312,7 +6154,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6399,7 +6241,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6492,7 +6334,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6568,7 +6410,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6623,14 +6465,10 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6647,7 +6485,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [buildFakeProvider(), buildFakeProvider()]; const fakeNetworkClients = [ buildFakeClient(fakeProviders[0]), @@ -6673,7 +6511,7 @@ describe('NetworkController', () => { controller, operation: async () => { const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkDidChange, operation: async () => { await controller.rollbackToPreviousProvider(); @@ -6688,14 +6526,10 @@ describe('NetworkController', () => { }); it('emits infuraIsBlocked or infuraIsUnblocked, depending on whether Infura is blocking requests for the previous network', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6712,7 +6546,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [ buildFakeProvider(), buildFakeProvider([ @@ -6744,12 +6578,12 @@ describe('NetworkController', () => { await controller.setActiveNetwork('testNetworkConfiguration'); const promiseForNoInfuraIsUnblockedEvents = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, count: 0, }); const promiseForInfuraIsBlocked = waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsBlocked, }); @@ -6770,7 +6604,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6846,7 +6680,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: networkType, // NOTE: This doesn't need to match the logical chain ID of // the network selected, it just needs to exist @@ -6940,7 +6774,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -6973,7 +6807,7 @@ describe('NetworkController', () => { }) .mockReturnValue(fakeNetworkClients[1]); await controller.setProviderType('goerli'); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ type: 'goerli', rpcUrl: undefined, chainId: '0x5', @@ -6990,7 +6824,7 @@ describe('NetworkController', () => { await controller.rollbackToPreviousProvider(); }, }); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7005,14 +6839,10 @@ describe('NetworkController', () => { }); it('emits networkWillChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7020,7 +6850,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [buildFakeProvider(), buildFakeProvider()]; const fakeNetworkClients = [ buildFakeClient(fakeProviders[0]), @@ -7045,7 +6875,7 @@ describe('NetworkController', () => { controller, operation: async () => { const networkWillChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkWillChange, operation: async () => { await controller.rollbackToPreviousProvider(); @@ -7063,7 +6893,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7139,7 +6969,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7219,7 +7049,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7286,7 +7116,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7332,14 +7162,10 @@ describe('NetworkController', () => { }); it('emits networkDidChange', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7347,7 +7173,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [buildFakeProvider(), buildFakeProvider()]; const fakeNetworkClients = [ buildFakeClient(fakeProviders[0]), @@ -7372,7 +7198,7 @@ describe('NetworkController', () => { controller, operation: async () => { const networkDidChange = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.NetworkDidChange, operation: async () => { await controller.rollbackToPreviousProvider(); @@ -7387,14 +7213,10 @@ describe('NetworkController', () => { }); it('emits infuraIsUnblocked', async () => { - const { unrestrictedMessenger, restrictedMessenger } = - buildMessengerGroup(); - await withController( { - messenger: restrictedMessenger, state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7402,7 +7224,7 @@ describe('NetworkController', () => { }, infuraProjectId: 'some-infura-project-id', }, - async ({ controller }) => { + async ({ controller, messenger }) => { const fakeProviders = [buildFakeProvider(), buildFakeProvider()]; const fakeNetworkClients = [ buildFakeClient(fakeProviders[0]), @@ -7427,7 +7249,7 @@ describe('NetworkController', () => { controller, operation: async () => { const infuraIsUnblocked = await waitForPublishedEvents({ - messenger: unrestrictedMessenger, + messenger, eventType: NetworkControllerEventType.InfuraIsUnblocked, operation: async () => { await controller.rollbackToPreviousProvider(); @@ -7445,7 +7267,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7510,7 +7332,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0x1337', @@ -7959,7 +7781,7 @@ describe('NetworkController', () => { it('should add the given network and not set it to active if the setActive option is not passed (or a falsy value is passed)', async () => { uuidV4Mock.mockImplementationOnce(() => 'networkConfigurationId'); - const originalProvider = { + const originalProviderConfig = { type: NETWORK_TYPES.RPC, rpcUrl: 'https://mock-rpc-url', chainId: '0xtest' as const, @@ -7968,7 +7790,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: originalProvider, + providerConfig: originalProviderConfig, networkConfigurations: { testNetworkConfigurationId: { rpcUrl: 'https://mock-rpc-url', @@ -7991,8 +7813,8 @@ describe('NetworkController', () => { source: MetaMetricsNetworkEventSource.Dapp, }); - expect(controller.store.getState().provider).toStrictEqual( - originalProvider, + expect(controller.store.getState().providerConfig).toStrictEqual( + originalProviderConfig, ); }, ); @@ -8003,7 +7825,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -8035,7 +7857,7 @@ describe('NetworkController', () => { source: MetaMetricsNetworkEventSource.Dapp, }); - expect(controller.store.getState().provider).toStrictEqual({ + expect(controller.store.getState().providerConfig).toStrictEqual({ ...rpcUrlNetwork, nickname: undefined, rpcPrefs: undefined, @@ -8052,7 +7874,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -8119,7 +7941,7 @@ describe('NetworkController', () => { await withController( { state: { - provider: { + providerConfig: { type: 'rpc', rpcUrl: 'https://mock-rpc-url', chainId: '0xtest', @@ -8239,18 +8061,22 @@ function mockCreateNetworkClient() { } /** - * Builds the set of controller messengers that recognizes the events that - * NetworkController emits: one designed to be used directly by - * NetworkController, and one designed to be used in tests. + * Builds a controller messenger. * * @returns The controller messenger. */ -function buildMessengerGroup() { - const unrestrictedMessenger = new ControllerMessenger< - never, - NetworkControllerEvent - >(); - const restrictedMessenger = unrestrictedMessenger.getRestricted< +function buildMessenger() { + return new ControllerMessenger(); +} + +/** + * Build a restricted controller messenger for the network controller. + * + * @param messenger - A controller messenger. + * @returns The network controller restricted messenger. + */ +function buildNetworkControllerMessenger(messenger = buildMessenger()) { + return messenger.getRestricted< 'NetworkController', never, NetworkControllerEventType @@ -8263,23 +8089,6 @@ function buildMessengerGroup() { NetworkControllerEventType.InfuraIsUnblocked, ], }); - return { unrestrictedMessenger, restrictedMessenger }; -} - -/** - * Despite the signature of its constructor, NetworkController must take an - * Infura project ID. The object that this function returns is mixed into the - * options first when a NetworkController is instantiated in tests. - * - * @returns The controller options. - */ -function buildDefaultNetworkControllerOptions() { - const { restrictedMessenger } = buildMessengerGroup(); - return { - messenger: restrictedMessenger, - infuraProjectId: DEFAULT_INFURA_PROJECT_ID, - trackMetaMetricsEvent: jest.fn(), - }; } /** @@ -8289,6 +8098,7 @@ type WithControllerCallback = ({ controller, }: { controller: NetworkController; + messenger: ControllerMessenger; }) => Promise | ReturnValue; /** @@ -8301,7 +8111,10 @@ type WithControllerOptions = Partial; */ type WithControllerArgs = | [WithControllerCallback] - | [WithControllerOptions, WithControllerCallback]; + | [ + Omit, + WithControllerCallback, + ]; /** * Builds a controller based on the given options, and calls the given function @@ -8318,13 +8131,16 @@ async function withController( ): Promise { const [givenNetworkControllerOptions, fn] = args.length === 2 ? args : [{}, args[0]]; - const networkControllerOptions = { - ...buildDefaultNetworkControllerOptions(), + const messenger = buildMessenger(); + const restrictedMessenger = buildNetworkControllerMessenger(messenger); + const controller = new NetworkController({ + infuraProjectId: DEFAULT_INFURA_PROJECT_ID, + messenger: restrictedMessenger, + trackMetaMetricsEvent: jest.fn(), ...givenNetworkControllerOptions, - }; - const controller = new NetworkController(networkControllerOptions); + }); try { - return await fn({ controller }); + return await fn({ controller, messenger }); } finally { await controller.destroy(); } diff --git a/app/scripts/controllers/network/network-controller.ts b/app/scripts/controllers/network/network-controller.ts index 545e47ccc..463565a54 100644 --- a/app/scripts/controllers/network/network-controller.ts +++ b/app/scripts/controllers/network/network-controller.ts @@ -266,7 +266,7 @@ type NetworkConfigurations = Record< * The state that NetworkController holds after combining its individual stores. */ export type NetworkControllerState = { - provider: ProviderConfiguration; + providerConfig: ProviderConfiguration; networkId: NetworkIdState; networkStatus: NetworkStatus; networkDetails: NetworkDetails; @@ -279,7 +279,7 @@ export type NetworkControllerState = { export type NetworkControllerOptions = { messenger: NetworkControllerMessenger; state?: { - provider?: ProviderConfiguration; + providerConfig?: ProviderConfiguration; networkDetails?: NetworkDetails; networkConfigurations?: NetworkConfigurations; }; @@ -327,7 +327,7 @@ function buildDefaultProviderConfigState(): ProviderConfiguration { }; } else if ( process.env.METAMASK_DEBUG || - process.env.METAMASK_ENV === 'test' + process.env.METAMASK_ENVIRONMENT === 'test' ) { return { type: NETWORK_TYPES.GOERLI, @@ -386,7 +386,7 @@ function buildDefaultNetworkConfigurationsState(): NetworkConfigurations { */ function buildDefaultState() { return { - provider: buildDefaultProviderConfigState(), + providerConfig: buildDefaultProviderConfigState(), networkId: buildDefaultNetworkIdState(), networkStatus: buildDefaultNetworkStatusState(), networkDetails: buildDefaultNetworkDetailsState(), @@ -477,7 +477,7 @@ export class NetworkController extends EventEmitter { ...buildDefaultState(), ...state, }); - this.#previousProviderConfig = this.store.getState().provider; + this.#previousProviderConfig = this.store.getState().providerConfig; // provider and block tracker this.#provider = null; @@ -508,7 +508,7 @@ export class NetworkController extends EventEmitter { * using the provider to gather details about the network. */ async initializeProvider(): Promise { - const { type, rpcUrl, chainId } = this.store.getState().provider; + const { type, rpcUrl, chainId } = this.store.getState().providerConfig; this.#configureProvider({ type, rpcUrl, chainId }); await this.lookupNetwork(); } @@ -575,7 +575,7 @@ export class NetworkController extends EventEmitter { * blocking requests, or if the network is not Infura-supported. */ async lookupNetwork(): Promise { - const { chainId, type } = this.store.getState().provider; + const { chainId, type } = this.store.getState().providerConfig; const { provider } = this.getProviderAndBlockTracker(); let networkChanged = false; let networkId: NetworkIdState = null; @@ -754,7 +754,7 @@ export class NetworkController extends EventEmitter { * Re-initializes the provider and block tracker for the current network. */ async resetConnection() { - await this.#setProviderConfig(this.store.getState().provider); + await this.#setProviderConfig(this.store.getState().providerConfig); } /** @@ -765,7 +765,7 @@ export class NetworkController extends EventEmitter { async rollbackToPreviousProvider() { const config = this.#previousProviderConfig; this.store.updateState({ - provider: config, + providerConfig: config, }); await this.#switchNetwork(config); } @@ -850,8 +850,8 @@ export class NetworkController extends EventEmitter { * @param providerConfig - The provider configuration. */ async #setProviderConfig(providerConfig: ProviderConfiguration) { - this.#previousProviderConfig = this.store.getState().provider; - this.store.updateState({ provider: providerConfig }); + this.#previousProviderConfig = this.store.getState().providerConfig; + this.store.updateState({ providerConfig }); await this.#switchNetwork(providerConfig); } diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index c091882ad..bcc708439 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -4,6 +4,6 @@ export * from './enums'; export * from './permission-log'; export * from './specifications'; export * from './selectors'; -///: BEGIN:ONLY_INCLUDE_IN(flask) -export * from './flask/snap-permissions'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +export * from './snaps/snap-permissions'; ///: END:ONLY_INCLUDE_IN diff --git a/app/scripts/controllers/permissions/flask/snap-permissions.js b/app/scripts/controllers/permissions/snaps/snap-permissions.js similarity index 100% rename from app/scripts/controllers/permissions/flask/snap-permissions.js rename to app/scripts/controllers/permissions/snaps/snap-permissions.js diff --git a/app/scripts/controllers/permissions/flask/snap-permissions.test.js b/app/scripts/controllers/permissions/snaps/snap-permissions.test.js similarity index 85% rename from app/scripts/controllers/permissions/flask/snap-permissions.test.js rename to app/scripts/controllers/permissions/snaps/snap-permissions.test.js index 8c53313ff..137f72f0b 100644 --- a/app/scripts/controllers/permissions/flask/snap-permissions.test.js +++ b/app/scripts/controllers/permissions/snaps/snap-permissions.test.js @@ -1,6 +1,7 @@ import { EndowmentPermissions, RestrictedMethods, + ExcludedSnapEndowments, } from '../../../../../shared/constants/permissions'; import { buildSnapEndowmentSpecifications, @@ -39,6 +40,13 @@ describe('buildSnapEndowmentSpecifications', () => { it('creates valid permission specification objects', () => { expect( Object.keys(buildSnapEndowmentSpecifications()).sort(), - ).toStrictEqual(Object.keys(EndowmentPermissions).sort()); + ).toStrictEqual( + Object.keys(EndowmentPermissions) + .filter( + (targetKey) => + !Object.keys(ExcludedSnapEndowments).includes(targetKey), + ) + .sort(), + ); }); }); diff --git a/app/scripts/controllers/permissions/specifications.js b/app/scripts/controllers/permissions/specifications.js index 4072398d1..b6f23d4be 100644 --- a/app/scripts/controllers/permissions/specifications.js +++ b/app/scripts/controllers/permissions/specifications.js @@ -2,7 +2,7 @@ import { constructPermission, PermissionType, } from '@metamask/permission-controller'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import { endowmentCaveatSpecifications as snapsEndowmentCaveatSpecifications } from '@metamask/snaps-controllers'; import { caveatSpecifications as snapsCaveatsSpecifications } from '@metamask/rpc-methods'; ///: END:ONLY_INCLUDE_IN @@ -71,7 +71,7 @@ export const getCaveatSpecifications = ({ getIdentities }) => { validateCaveatAccounts(caveat.value, getIdentities), }, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) ...snapsCaveatsSpecifications, ...snapsEndowmentCaveatSpecifications, ///: END:ONLY_INCLUDE_IN diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js deleted file mode 100644 index 9249c907e..000000000 --- a/app/scripts/lib/decrypt-message-manager.js +++ /dev/null @@ -1,351 +0,0 @@ -import EventEmitter from 'events'; -import { ObservableStore } from '@metamask/obs-store'; -import { bufferToHex } from 'ethereumjs-util'; -import { ethErrors } from 'eth-rpc-errors'; -import log from 'loglevel'; -import { MESSAGE_TYPE } from '../../../shared/constants/app'; -import { MetaMetricsEventCategory } from '../../../shared/constants/metametrics'; -import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; -import createId from '../../../shared/modules/random-id'; -import { stripHexPrefix } from '../../../shared/modules/hexstring-utils'; -import { addHexPrefix } from './util'; - -const hexRe = /^[0-9A-Fa-f]+$/gu; - -/** - * Represents, and contains data about, an 'eth_decrypt' type decryption request. These are created when a - * decryption for an eth_decrypt call is requested. - * - * @typedef {object} DecryptMessage - * @property {number} id An id to track and identify the message object - * @property {object} msgParams The parameters to pass to the decryptMessage method once the decryption request is - * approved. - * @property {object} msgParams.metamaskId Added to msgParams for tracking and identification within MetaMask. - * @property {string} msgParams.data A hex string conversion of the raw buffer data of the decryption request - * @property {number} time The epoch time at which the this message was created - * @property {string} status Indicates whether the decryption request is 'unapproved', 'approved', 'decrypted' or 'rejected' - * @property {string} type The json-prc decryption method for which a decryption request has been made. A 'Message' will - * always have a 'eth_decrypt' type. - */ - -export default class DecryptMessageManager extends EventEmitter { - /** - * Controller in charge of managing - storing, adding, removing, updating - DecryptMessage. - * - * @param {object} opts - Controller options - * @param {Function} opts.metricEvent - A function for emitting a metric event. - */ - constructor(opts) { - super(); - this.memStore = new ObservableStore({ - unapprovedDecryptMsgs: {}, - unapprovedDecryptMsgCount: 0, - }); - - this.resetState = () => { - this.memStore.updateState({ - unapprovedDecryptMsgs: {}, - unapprovedDecryptMsgCount: 0, - }); - }; - - this.messages = []; - this.metricsEvent = opts.metricsEvent; - } - - /** - * A getter for the number of 'unapproved' DecryptMessages in this.messages - * - * @returns {number} The number of 'unapproved' DecryptMessages in this.messages - */ - get unapprovedDecryptMsgCount() { - return Object.keys(this.getUnapprovedMsgs()).length; - } - - /** - * A getter for the 'unapproved' DecryptMessages in this.messages - * - * @returns {object} An index of DecryptMessage ids to DecryptMessages, for all 'unapproved' DecryptMessages in - * this.messages - */ - getUnapprovedMsgs() { - return this.messages - .filter((msg) => msg.status === 'unapproved') - .reduce((result, msg) => { - result[msg.id] = msg; - return result; - }, {}); - } - - /** - * Creates a new DecryptMessage with an 'unapproved' status using the passed msgParams. this.addMsg is called to add - * the new DecryptMessage to this.messages, and to save the unapproved DecryptMessages from that list to - * this.memStore. - * - * @param {object} msgParams - The params for the eth_decrypt call to be made after the message is approved. - * @param {object} [req] - The original request object possibly containing the origin - * @returns {Promise} The raw decrypted message contents - */ - addUnapprovedMessageAsync(msgParams, req) { - return new Promise((resolve, reject) => { - if (!msgParams.from) { - reject(new Error('MetaMask Decryption: from field is required.')); - return; - } - const msgId = this.addUnapprovedMessage(msgParams, req); - this.once(`${msgId}:finished`, (data) => { - switch (data.status) { - case 'decrypted': - resolve(data.rawData); - return; - case 'rejected': - reject( - ethErrors.provider.userRejectedRequest( - 'MetaMask Decryption: User denied message decryption.', - ), - ); - return; - case 'errored': - reject(new Error('This message cannot be decrypted')); - return; - default: - reject( - new Error( - `MetaMask Decryption: Unknown problem: ${JSON.stringify( - msgParams, - )}`, - ), - ); - } - }); - }); - } - - /** - * Creates a new DecryptMessage with an 'unapproved' status using the passed msgParams. this.addMsg is called to add - * the new DecryptMessage to this.messages, and to save the unapproved DecryptMessages from that list to - * this.memStore. - * - * @param {object} msgParams - The params for the eth_decryptMsg call to be made after the message is approved. - * @param {object} [req] - The original request object possibly containing the origin - * @returns {number} The id of the newly created DecryptMessage. - */ - addUnapprovedMessage(msgParams, req) { - log.debug( - `DecryptMessageManager addUnapprovedMessage: ${JSON.stringify( - msgParams, - )}`, - ); - // add origin from request - if (req) { - msgParams.origin = req.origin; - } - msgParams.data = this.normalizeMsgData(msgParams.data); - // create txData obj with parameters and meta data - const time = new Date().getTime(); - const msgId = createId(); - const msgData = { - id: msgId, - msgParams, - time, - status: 'unapproved', - type: MESSAGE_TYPE.ETH_DECRYPT, - }; - this.addMsg(msgData); - - // signal update - this.emit('update'); - return msgId; - } - - /** - * Adds a passed DecryptMessage to this.messages, and calls this._saveMsgList() to save the unapproved DecryptMessages from that - * list to this.memStore. - * - * @param {Message} msg - The DecryptMessage to add to this.messages - */ - addMsg(msg) { - this.messages.push(msg); - this._saveMsgList(); - } - - /** - * Returns a specified DecryptMessage. - * - * @param {number} msgId - The id of the DecryptMessage to get - * @returns {DecryptMessage|undefined} The DecryptMessage with the id that matches the passed msgId, or undefined - * if no DecryptMessage has that id. - */ - getMsg(msgId) { - return this.messages.find((msg) => msg.id === msgId); - } - - /** - * Approves a DecryptMessage. Sets the message status via a call to this.setMsgStatusApproved, and returns a promise - * with the message params modified for proper decryption. - * - * @param {object} msgParams - The msgParams to be used when eth_decryptMsg is called, plus data added by MetaMask. - * @param {object} msgParams.metamaskId - Added to msgParams for tracking and identification within MetaMask. - * @returns {Promise} Promises the msgParams object with metamaskId removed. - */ - approveMessage(msgParams) { - this.setMsgStatusApproved(msgParams.metamaskId); - return this.prepMsgForDecryption(msgParams); - } - - /** - * Sets a DecryptMessage status to 'approved' via a call to this._setMsgStatus. - * - * @param {number} msgId - The id of the DecryptMessage to approve. - */ - setMsgStatusApproved(msgId) { - this._setMsgStatus(msgId, 'approved'); - } - - /** - * Sets a DecryptMessage status to 'decrypted' via a call to this._setMsgStatus and updates that DecryptMessage in - * this.messages by adding the raw decryption data of the decryption request to the DecryptMessage - * - * @param {number} msgId - The id of the DecryptMessage to decrypt. - * @param {buffer} rawData - The raw data of the message request - */ - setMsgStatusDecrypted(msgId, rawData) { - const msg = this.getMsg(msgId); - msg.rawData = rawData; - this._updateMsg(msg); - this._setMsgStatus(msgId, 'decrypted'); - } - - /** - * Removes the metamaskId property from passed msgParams and returns a promise which resolves the updated msgParams - * - * @param {object} msgParams - The msgParams to modify - * @returns {Promise} Promises the msgParams with the metamaskId property removed - */ - async prepMsgForDecryption(msgParams) { - delete msgParams.metamaskId; - return msgParams; - } - - /** - * Sets a DecryptMessage status to 'rejected' via a call to this._setMsgStatus. - * - * @param {number} msgId - The id of the DecryptMessage to reject. - * @param reason - */ - rejectMsg(msgId, reason = undefined) { - if (reason) { - this.metricsEvent({ - event: reason, - category: MetaMetricsEventCategory.Messages, - properties: { - action: 'Decrypt Message Request', - }, - }); - } - this._setMsgStatus(msgId, 'rejected'); - } - - /** - * Sets a TypedMessage status to 'errored' via a call to this._setMsgStatus. - * - * @param {number} msgId - The id of the TypedMessage to error - * @param error - */ - errorMessage(msgId, error) { - const msg = this.getMsg(msgId); - msg.error = error; - this._updateMsg(msg); - this._setMsgStatus(msgId, 'errored'); - } - - /** - * Clears all unapproved messages from memory. - */ - clearUnapproved() { - this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); - this._saveMsgList(); - } - - /** - * Updates the status of a DecryptMessage in this.messages via a call to this._updateMsg - * - * @private - * @param {number} msgId - The id of the DecryptMessage to update. - * @param {string} status - The new status of the DecryptMessage. - * @throws A 'DecryptMessageManager - DecryptMessage not found for id: "${msgId}".' if there is no DecryptMessage - * in this.messages with an id equal to the passed msgId - * @fires An event with a name equal to `${msgId}:${status}`. The DecryptMessage is also fired. - * @fires If status is 'rejected' or 'decrypted', an event with a name equal to `${msgId}:finished` is fired along - * with the DecryptMessage - */ - _setMsgStatus(msgId, status) { - const msg = this.getMsg(msgId); - if (!msg) { - throw new Error( - `DecryptMessageManager - Message not found for id: "${msgId}".`, - ); - } - msg.status = status; - this._updateMsg(msg); - this.emit(`${msgId}:${status}`, msg); - if ( - status === 'rejected' || - status === 'decrypted' || - status === 'errored' - ) { - this.emit(`${msgId}:finished`, msg); - } - } - - /** - * Sets a DecryptMessage in this.messages to the passed DecryptMessage if the ids are equal. Then saves the - * unapprovedDecryptMsgs index to storage via this._saveMsgList - * - * @private - * @param {DecryptMessage} msg - A DecryptMessage that will replace an existing DecryptMessage (with the same - * id) in this.messages - */ - _updateMsg(msg) { - const index = this.messages.findIndex((message) => message.id === msg.id); - if (index !== -1) { - this.messages[index] = msg; - } - this._saveMsgList(); - } - - /** - * Saves the unapproved DecryptMessages, and their count, to this.memStore - * - * @private - * @fires 'updateBadge' - */ - _saveMsgList() { - const unapprovedDecryptMsgs = this.getUnapprovedMsgs(); - const unapprovedDecryptMsgCount = Object.keys(unapprovedDecryptMsgs).length; - this.memStore.updateState({ - unapprovedDecryptMsgs, - unapprovedDecryptMsgCount, - }); - this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); - } - - /** - * A helper function that converts raw buffer data to a hex, or just returns the data if it is already formatted as a hex. - * - * @param {any} data - The buffer data to convert to a hex - * @returns {string} A hex string conversion of the buffer data - */ - normalizeMsgData(data) { - try { - const stripped = stripHexPrefix(data); - if (stripped.match(hexRe)) { - return addHexPrefix(stripped); - } - } catch (e) { - log.debug(`Message was not hex encoded, interpreting as utf8.`); - } - - return bufferToHex(Buffer.from(data, 'utf8')); - } -} diff --git a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js index 8815b6556..3b1530767 100644 --- a/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js +++ b/app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js @@ -1,5 +1,5 @@ -///: BEGIN:ONLY_INCLUDE_IN(flask) -import { handlers as permittedSnapMethods } from '@metamask/rpc-methods/dist/permitted'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +import { permittedMethods as permittedSnapMethods } from '@metamask/rpc-methods'; ///: END:ONLY_INCLUDE_IN import { permissionRpcMethods } from '@metamask/permission-controller'; import { selectHooks } from '@metamask/rpc-methods/dist/utils'; @@ -72,7 +72,7 @@ export function createMethodMiddleware(hooks) { }; } -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) const snapHandlerMap = permittedSnapMethods.reduce((map, handler) => { for (const methodName of handler.methodNames) { map.set(methodName, handler); diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index bc0150b84..a383f8221 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -1,7 +1,6 @@ import * as Sentry from '@sentry/browser'; import { Dedupe, ExtraErrorData } from '@sentry/integrations'; -import { BuildType } from '../../../shared/constants/app'; import { FilterEvents } from './sentry-filter-events'; import extractEthjsErrorMessage from './extractEthjsErrorMessage'; @@ -57,7 +56,7 @@ export const SENTRY_STATE = { nextNonce: true, participateInMetaMetrics: true, preferences: true, - provider: { + providerConfig: { nickname: true, ticker: true, type: true, @@ -90,7 +89,7 @@ export default function setupSentry({ release, getState }) { } const environment = - METAMASK_BUILD_TYPE === BuildType.main + METAMASK_BUILD_TYPE === 'main' ? METAMASK_ENVIRONMENT : `${METAMASK_ENVIRONMENT}-${METAMASK_BUILD_TYPE}`; diff --git a/app/scripts/lockdown-run.js b/app/scripts/lockdown-run.js index 0d869cc7f..b86c2c507 100644 --- a/app/scripts/lockdown-run.js +++ b/app/scripts/lockdown-run.js @@ -6,6 +6,7 @@ try { errorTaming: 'unsafe', mathTaming: 'unsafe', dateTaming: 'unsafe', + domainTaming: 'unsafe', overrideTaming: 'severe', }); } catch (error) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0517828fa..601091454 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -48,12 +48,12 @@ import { SubjectMetadataController, SubjectType, } from '@metamask/subject-metadata-controller'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import { RateLimitController } from '@metamask/rate-limit-controller'; import { NotificationController } from '@metamask/notification-controller'; ///: END:ONLY_INCLUDE_IN import SmartTransactionsController from '@metamask/smart-transactions-controller'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import { CronjobController, JsonSnapsRegistry, @@ -83,19 +83,18 @@ import { KeyringType } from '../../shared/constants/keyring'; import { CaveatTypes, RestrictedMethods, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) EndowmentPermissions, ExcludedSnapPermissions, ExcludedSnapEndowments, ///: END:ONLY_INCLUDE_IN } from '../../shared/constants/permissions'; import { UI_NOTIFICATIONS } from '../../shared/notifications'; -import { stripHexPrefix } from '../../shared/modules/hexstring-utils'; import { MILLISECOND, SECOND } from '../../shared/constants/time'; import { ORIGIN_METAMASK, MESSAGE_TYPE, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) SNAP_DIALOG_TYPES, ///: END:ONLY_INCLUDE_IN POLLING_TOKEN_ENVIRONMENT_TYPES, @@ -115,8 +114,7 @@ import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens'; import { getTokenValueParam } from '../../shared/lib/metamask-controller-utils'; import { isManifestV3 } from '../../shared/modules/mv3.utils'; import { hexToDecimal } from '../../shared/modules/conversion.utils'; -///: BEGIN:ONLY_INCLUDE_IN(flask) -import { isMain, isFlask } from '../../shared/constants/environment'; +///: BEGIN:ONLY_INCLUDE_IN(desktop) // eslint-disable-next-line import/order import { DesktopController } from '@metamask/desktop/dist/controllers/desktop'; ///: END:ONLY_INCLUDE_IN @@ -131,7 +129,7 @@ import createDupeReqFilterMiddleware from './lib/createDupeReqFilterMiddleware'; import createLoggerMiddleware from './lib/createLoggerMiddleware'; import { createMethodMiddleware, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) createSnapMethodMiddleware, ///: END:ONLY_INCLUDE_IN } from './lib/rpc-method-middleware'; @@ -151,7 +149,7 @@ import AlertController from './controllers/alert'; import OnboardingController from './controllers/onboarding'; import BackupController from './controllers/backup'; import IncomingTransactionsController from './controllers/incoming-transactions'; -import DecryptMessageManager from './lib/decrypt-message-manager'; +import DecryptMessageController from './controllers/decrypt-message'; import TransactionController from './controllers/transactions'; import DetectTokensController from './controllers/detect-tokens'; import SwapsController from './controllers/swaps'; @@ -175,7 +173,7 @@ import { NOTIFICATION_NAMES, PermissionLogController, unrestrictedMethods, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) buildSnapEndowmentSpecifications, buildSnapRestrictedMethodSpecifications, ///: END:ONLY_INCLUDE_IN @@ -287,7 +285,7 @@ export default class MetamaskController extends EventEmitter { this.tokenListController = new TokenListController({ chainId: hexToDecimal( - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, ), preventPollingOnNetworkRestart: initState.TokenListController ? initState.TokenListController.preventPollingOnNetworkRestart @@ -297,8 +295,8 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: hexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: hexToDecimal(networkState.providerConfig.chainId), }, }; return cb(modifiedNetworkState); @@ -332,13 +330,21 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, + ...networkState.providerConfig, }, }; return cb(modifiedNetworkState); }), config: { provider: this.provider }, state: initState.TokensController, + messenger: this.controllerMessenger.getRestricted({ + name: 'TokensController', + allowedActions: [ + `${this.approvalController.name}:addRequest`, + `${this.approvalController.name}:acceptRequest`, + `${this.approvalController.name}:rejectRequest`, + ], + }), }); this.assetsContractController = new AssetsContractController( @@ -361,8 +367,8 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: hexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: hexToDecimal(networkState.providerConfig.chainId), }, }; return cb(modifiedNetworkState); @@ -386,8 +392,8 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: hexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: hexToDecimal(networkState.providerConfig.chainId), }, }; return cb(modifiedNetworkState); @@ -446,8 +452,8 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: hexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: hexToDecimal(networkState.providerConfig.chainId), }, }; return cb(modifiedNetworkState); @@ -470,11 +476,11 @@ export default class MetamaskController extends EventEmitter { ), getNetworkIdentifier: () => { const { type, rpcUrl } = - this.networkController.store.getState().provider; + this.networkController.store.getState().providerConfig; return type === NETWORK_TYPES.RPC ? rpcUrl : type; }, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, version: this.platform.getVersion(), environment: process.env.METAMASK_ENVIRONMENT, extension: this.extension, @@ -516,13 +522,14 @@ export default class MetamaskController extends EventEmitter { legacyAPIEndpoint: `${gasApiBaseUrl}/networks//gasPrices`, EIP1559APIEndpoint: `${gasApiBaseUrl}/networks//suggestedGasFees`, getCurrentNetworkLegacyGasAPICompatibility: () => { - const { chainId } = this.networkController.store.getState().provider; + const { chainId } = + this.networkController.store.getState().providerConfig; return process.env.IN_TEST || chainId === CHAIN_IDS.MAINNET; }, getChainId: () => { return process.env.IN_TEST ? CHAIN_IDS.MAINNET - : this.networkController.store.getState().provider.chainId; + : this.networkController.store.getState().providerConfig.chainId; }, }); @@ -552,7 +559,8 @@ export default class MetamaskController extends EventEmitter { messenger: currencyRateMessenger, state: { ...initState.CurrencyController, - nativeCurrency: this.networkController.store.getState().provider.ticker, + nativeCurrency: + this.networkController.store.getState().providerConfig.ticker, }, }); @@ -592,8 +600,8 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, - chainId: hexToDecimal(networkState.provider.chainId), + ...networkState.providerConfig, + chainId: hexToDecimal(networkState.providerConfig.chainId), }, }; return cb(modifiedNetworkState); @@ -626,7 +634,7 @@ export default class MetamaskController extends EventEmitter { this.ensController = new EnsController({ provider: this.provider, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, onNetworkDidChange: networkControllerMessenger.subscribe.bind( networkControllerMessenger, NetworkControllerEventType.NetworkDidChange, @@ -644,7 +652,7 @@ export default class MetamaskController extends EventEmitter { NetworkControllerEventType.NetworkDidChange, ), getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, preferencesController: this.preferencesController, onboardingController: this.onboardingController, initState: initState.IncomingTransactionsController, @@ -655,10 +663,10 @@ export default class MetamaskController extends EventEmitter { provider: this.provider, blockTracker: this.blockTracker, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, getNetworkIdentifier: () => { const { type, rpcUrl } = - this.networkController.store.getState().provider; + this.networkController.store.getState().providerConfig; return type === NETWORK_TYPES.RPC ? rpcUrl : type; }, preferencesController: this.preferencesController, @@ -695,14 +703,10 @@ export default class MetamaskController extends EventEmitter { this.cachedBalancesController = new CachedBalancesController({ accountTracker: this.accountTracker, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, initState: initState.CachedBalancesController, }); - this.tokensController.hub.on('pendingSuggestedAsset', async () => { - await opts.openPopup(); - }); - let additionalKeyrings = [keyringBuilderFactory(QRHardwareKeyring)]; if (this.canUseHardwareWallets()) { @@ -782,7 +786,7 @@ export default class MetamaskController extends EventEmitter { ); }, }), - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) ...this.getSnapPermissionSpecifications(), ///: END:ONLY_INCLUDE_IN }, @@ -803,7 +807,7 @@ export default class MetamaskController extends EventEmitter { subjectCacheLimit: 100, }); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) const snapExecutionServiceArgs = { iframeUrl: new URL('https://execution.metamask.io/0.15.1/index.html'), messenger: this.controllerMessenger.getRestricted({ @@ -848,6 +852,9 @@ export default class MetamaskController extends EventEmitter { ], }); + const allowLocalSnaps = process.env.ALLOW_LOCAL_SNAPS; + const requireAllowlist = process.env.REQUIRE_SNAPS_ALLOWLIST; + this.snapController = new SnapController({ environmentEndowmentPermissions: Object.values(EndowmentPermissions), excludedPermissions: { @@ -859,8 +866,8 @@ export default class MetamaskController extends EventEmitter { messenger: snapControllerMessenger, featureFlags: { dappsCanUpdateSnaps: true, - allowLocalSnaps: isFlask, - requireAllowlist: isMain, + allowLocalSnaps, + requireAllowlist, }, }); @@ -929,8 +936,8 @@ export default class MetamaskController extends EventEmitter { this.snapsRegistry = new JsonSnapsRegistry({ state: initState.SnapsRegistry, messenger: snapsRegistryMessenger, - refetchOnAllowlistMiss: isMain, - failOnUnavailableRegistry: isMain, + refetchOnAllowlistMiss: requireAllowlist, + failOnUnavailableRegistry: requireAllowlist, url: { registry: 'https://acl.execution.metamask.io/latest/registry.json', signature: 'https://acl.execution.metamask.io/latest/signature.json', @@ -939,6 +946,9 @@ export default class MetamaskController extends EventEmitter { '0x025b65308f0f0fb8bc7f7ff87bfc296e0330eee5d3c1d1ee4a048b2fd6a86fa0a6', }); + ///: END:ONLY_INCLUDE_IN + + ///: BEGIN:ONLY_INCLUDE_IN(desktop) this.desktopController = new DesktopController({ initState: initState.DesktopController, }); @@ -979,7 +989,8 @@ export default class MetamaskController extends EventEmitter { initState: initState.TransactionController || initState.TransactionManager, getPermittedAccounts: this.getPermittedAccounts.bind(this), - getProviderConfig: () => this.networkController.store.getState().provider, + getProviderConfig: () => + this.networkController.store.getState().providerConfig, getCurrentNetworkEIP1559Compatibility: this.networkController.getEIP1559Compatibility.bind( this.networkController, @@ -1000,7 +1011,7 @@ export default class MetamaskController extends EventEmitter { }); }, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, preferencesStore: this.preferencesController.store, txHistoryLimit: 60, signTransaction: this.keyringController.signTransaction.bind( @@ -1136,7 +1147,8 @@ export default class MetamaskController extends EventEmitter { networkControllerMessenger.subscribe( NetworkControllerEventType.NetworkDidChange, async () => { - const { ticker } = this.networkController.store.getState().provider; + const { ticker } = + this.networkController.store.getState().providerConfig; try { await this.currencyRateController.setNativeCurrency(ticker); } catch (error) { @@ -1147,7 +1159,17 @@ export default class MetamaskController extends EventEmitter { ); this.networkController.lookupNetwork(); - this.decryptMessageManager = new DecryptMessageManager({ + this.decryptMessageController = new DecryptMessageController({ + getState: this.getState.bind(this), + keyringController: this.keyringController, + messenger: this.controllerMessenger.getRestricted({ + name: 'DecryptMessageController', + allowedActions: [ + `${this.approvalController.name}:addRequest`, + `${this.approvalController.name}:acceptRequest`, + `${this.approvalController.name}:rejectRequest`, + ], + }), metricsEvent: this.metaMetricsController.trackEvent.bind( this.metaMetricsController, ), @@ -1195,10 +1217,11 @@ export default class MetamaskController extends EventEmitter { onNetworkStateChange: (listener) => this.networkController.store.subscribe(listener), provider: this.provider, - getProviderConfig: () => this.networkController.store.getState().provider, + getProviderConfig: () => + this.networkController.store.getState().providerConfig, getTokenRatesState: () => this.tokenRatesController.state, getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, getEIP1559GasFeeEstimates: this.gasFeeController.fetchGasFeeEstimates.bind(this.gasFeeController), }); @@ -1209,7 +1232,7 @@ export default class MetamaskController extends EventEmitter { const modifiedNetworkState = { ...networkState, providerConfig: { - ...networkState.provider, + ...networkState.providerConfig, }, }; return cb(modifiedNetworkState); @@ -1247,12 +1270,12 @@ export default class MetamaskController extends EventEmitter { () => { this.txController.txStateManager.clearUnapprovedTxs(); this.encryptionPublicKeyController.clearUnapproved(); - this.decryptMessageManager.clearUnapproved(); + this.decryptMessageController.clearUnapproved(); this.signController.clearUnapproved(); }, ); - if (isManifestV3 && globalThis.isFirstTimeProfileLoaded === false) { + if (isManifestV3 && globalThis.isFirstTimeProfileLoaded === undefined) { const { serviceWorkerLastActiveTime } = this.appStateController.store.getState(); const metametricsPayload = { @@ -1312,11 +1335,14 @@ export default class MetamaskController extends EventEmitter { this.signController.newUnsignedPersonalMessage.bind( this.signController, ), - processDecryptMessage: this.newRequestDecryptMessage.bind(this), processEncryptionPublicKey: this.encryptionPublicKeyController.newRequestEncryptionPublicKey.bind( this.encryptionPublicKeyController, ), + processDecryptMessage: + this.decryptMessageController.newRequestDecryptMessage.bind( + this.decryptMessageController, + ), getPendingNonce: this.getPendingNonce.bind(this), getPendingTransactionByHash: (hash) => this.txController.getTransactions({ @@ -1338,7 +1364,7 @@ export default class MetamaskController extends EventEmitter { AccountTracker: this.accountTracker.store, TxController: this.txController.memStore, TokenRatesController: this.tokenRatesController, - DecryptMessageManager: this.decryptMessageManager.memStore, + DecryptMessageController: this.decryptMessageController, EncryptionPublicKeyController: this.encryptionPublicKeyController, SignController: this.signController, SwapsController: this.swapsController.store, @@ -1370,11 +1396,13 @@ export default class MetamaskController extends EventEmitter { SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, PhishingController: this.phishingController, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) SnapController: this.snapController, CronjobController: this.cronjobController, SnapsRegistry: this.snapsRegistry, NotificationController: this.notificationController, + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) DesktopController: this.desktopController.store, ///: END:ONLY_INCLUDE_IN ...resetOnRestartStore, @@ -1404,11 +1432,13 @@ export default class MetamaskController extends EventEmitter { TokensController: this.tokensController, SmartTransactionsController: this.smartTransactionsController, NftController: this.nftController, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) SnapController: this.snapController, CronjobController: this.cronjobController, SnapsRegistry: this.snapsRegistry, NotificationController: this.notificationController, + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) DesktopController: this.desktopController.store, ///: END:ONLY_INCLUDE_IN ...resetOnRestartStore, @@ -1420,7 +1450,9 @@ export default class MetamaskController extends EventEmitter { const resetMethods = [ this.accountTracker.resetState, this.txController.resetState, - this.decryptMessageManager.resetState, + this.decryptMessageController.resetState.bind( + this.decryptMessageController, + ), this.encryptionPublicKeyController.resetState.bind( this.encryptionPublicKeyController, ), @@ -1500,7 +1532,7 @@ export default class MetamaskController extends EventEmitter { } canUseHardwareWallets() { - return !isManifestV3 || process.env.CONF?.HARDWARE_WALLETS_MV3; + return !isManifestV3 || process.env.HARDWARE_WALLETS_MV3; } resetStates(resetMethods) { @@ -1513,7 +1545,7 @@ export default class MetamaskController extends EventEmitter { }); } - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) /** * Constructor helper for getting Snap permission specifications. */ @@ -1655,7 +1687,7 @@ export default class MetamaskController extends EventEmitter { getPermittedAccountsByOrigin, ); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) // Record Snap metadata whenever a Snap is added to state. this.controllerMessenger.subscribe( `${this.snapController.name}:snapAdded`, @@ -1756,7 +1788,7 @@ export default class MetamaskController extends EventEmitter { updatePublicConfigStore(this.getState()); function updatePublicConfigStore(memState) { - const { chainId } = networkController.store.getState().provider; + const { chainId } = networkController.store.getState().providerConfig; if (memState.networkStatus === NetworkStatus.Available) { publicConfigStore.putState(selectPublicState(chainId, memState)); } @@ -1797,7 +1829,7 @@ export default class MetamaskController extends EventEmitter { getProviderNetworkState(memState) { const { networkId } = memState || this.getState(); return { - chainId: this.networkController.store.getState().provider.chainId, + chainId: this.networkController.store.getState().providerConfig.chainId, networkVersion: networkId ?? 'loading', }; } @@ -1956,6 +1988,10 @@ export default class MetamaskController extends EventEmitter { this.networkController.upsertNetworkConfiguration.bind( this.networkController, ), + getCurrentNetworkEIP1559Compatibility: + this.networkController.getEIP1559Compatibility.bind( + this.networkController, + ), // PreferencesController setSelectedAddress: preferencesController.setSelectedAddress.bind( preferencesController, @@ -2057,6 +2093,8 @@ export default class MetamaskController extends EventEmitter { ), setShowBetaHeader: appStateController.setShowBetaHeader.bind(appStateController), + setShowProductTour: + appStateController.setShowProductTour.bind(appStateController), updateNftDropDownState: appStateController.updateNftDropDownState.bind(appStateController), setFirstTimeUsedNetwork: @@ -2122,10 +2160,18 @@ export default class MetamaskController extends EventEmitter { this.signController, ), - // decryptMessageManager - decryptMessage: this.decryptMessage.bind(this), - decryptMessageInline: this.decryptMessageInline.bind(this), - cancelDecryptMessage: this.cancelDecryptMessage.bind(this), + // decryptMessageController + decryptMessage: this.decryptMessageController.decryptMessage.bind( + this.decryptMessageController, + ), + decryptMessageInline: + this.decryptMessageController.decryptMessageInline.bind( + this.decryptMessageController, + ), + cancelDecryptMessage: + this.decryptMessageController.cancelDecryptMessage.bind( + this.decryptMessageController, + ), // EncryptionPublicKeyController encryptionPublicKey: @@ -2159,7 +2205,7 @@ export default class MetamaskController extends EventEmitter { rejectPermissionsRequest: this.rejectPermissionsRequest, ...getPermissionBackgroundApiMethods(permissionController), - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) // snaps removeSnapError: this.controllerMessenger.call.bind( this.controllerMessenger, @@ -2183,6 +2229,8 @@ export default class MetamaskController extends EventEmitter { ), dismissNotifications: this.dismissNotifications.bind(this), markNotificationsAsRead: this.markNotificationsAsRead.bind(this), + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) // Desktop getDesktopEnabled: this.desktopController.getDesktopEnabled.bind( this.desktopController, @@ -2482,7 +2530,7 @@ export default class MetamaskController extends EventEmitter { // clear permissions this.permissionController.clearState(); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) // Clear snap state this.snapController.clearState(); // Clear notification state @@ -2608,7 +2656,7 @@ export default class MetamaskController extends EventEmitter { async _loginUser() { try { // Automatic login via config password - const password = process.env.CONF?.PASSWORD; + const password = process.env.PASSWORD; if (password && !process.env.IN_TEST) { await this.submitPassword(password); } @@ -2753,7 +2801,8 @@ export default class MetamaskController extends EventEmitter { this.appStateController.setTrezorModel(model); } - keyring.network = this.networkController.store.getState().provider.type; + keyring.network = + this.networkController.store.getState().providerConfig.type; return keyring; } @@ -3141,95 +3190,6 @@ export default class MetamaskController extends EventEmitter { return await this.txController.newUnapprovedTransaction(txParams, req); } - // eth_decrypt methods - - /** - * Called when a dapp uses the eth_decrypt method. - * - * @param {object} msgParams - The params of the message to sign & return to the Dapp. - * @param {object} req - (optional) the original request, containing the origin - * Passed back to the requesting Dapp. - */ - async newRequestDecryptMessage(msgParams, req) { - const promise = this.decryptMessageManager.addUnapprovedMessageAsync( - msgParams, - req, - ); - this.sendUpdate(); - this.opts.showUserConfirmation(); - return promise; - } - - /** - * Only decrypt message and don't touch transaction state - * - * @param {object} msgParams - The params of the message to decrypt. - * @returns {Promise} A full state update. - */ - async decryptMessageInline(msgParams) { - log.info('MetaMaskController - decryptMessageInline'); - // decrypt the message inline - const msgId = msgParams.metamaskId; - const msg = this.decryptMessageManager.getMsg(msgId); - try { - const stripped = stripHexPrefix(msgParams.data); - const buff = Buffer.from(stripped, 'hex'); - msgParams.data = JSON.parse(buff.toString('utf8')); - - msg.rawData = await this.keyringController.decryptMessage(msgParams); - } catch (e) { - msg.error = e.message; - } - this.decryptMessageManager._updateMsg(msg); - - return this.getState(); - } - - /** - * Signifies a user's approval to decrypt a message in queue. - * Triggers decrypt, and the callback function from newUnsignedDecryptMessage. - * - * @param {object} msgParams - The params of the message to decrypt & return to the Dapp. - * @returns {Promise} A full state update. - */ - async decryptMessage(msgParams) { - log.info('MetaMaskController - decryptMessage'); - const msgId = msgParams.metamaskId; - // sets the status op the message to 'approved' - // and removes the metamaskId for decryption - try { - const cleanMsgParams = await this.decryptMessageManager.approveMessage( - msgParams, - ); - - const stripped = stripHexPrefix(cleanMsgParams.data); - const buff = Buffer.from(stripped, 'hex'); - cleanMsgParams.data = JSON.parse(buff.toString('utf8')); - - // decrypt the message - const rawMess = await this.keyringController.decryptMessage( - cleanMsgParams, - ); - // tells the listener that the message has been decrypted and can be returned to the dapp - this.decryptMessageManager.setMsgStatusDecrypted(msgId, rawMess); - } catch (error) { - log.info('MetaMaskController - eth_decrypt failed.', error); - this.decryptMessageManager.errorMessage(msgId, error); - } - return this.getState(); - } - - /** - * Used to cancel a eth_decrypt type message. - * - * @param {string} msgId - The ID of the message to cancel. - */ - cancelDecryptMessage(msgId) { - const messageManager = this.decryptMessageManager; - messageManager.rejectMsg(msgId); - return this.getState(); - } - /** * @returns {boolean} true if the keyring type supports EIP-1559 */ @@ -3537,7 +3497,7 @@ export default class MetamaskController extends EventEmitter { if (subjectType === SubjectType.Internal) { origin = ORIGIN_METAMASK; } - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) else if (subjectType === SubjectType.Snap) { origin = sender.snapId; } @@ -3585,7 +3545,7 @@ export default class MetamaskController extends EventEmitter { }); } - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) /** * For snaps running in workers. * @@ -3714,9 +3674,9 @@ export default class MetamaskController extends EventEmitter { ), getCurrentChainId: () => - this.networkController.store.getState().provider.chainId, + this.networkController.store.getState().providerConfig.chainId, getCurrentRpcUrl: () => - this.networkController.store.getState().provider.rpcUrl, + this.networkController.store.getState().providerConfig.rpcUrl, // network configuration-related getNetworkConfigurations: () => this.networkController.store.getState().networkConfigurations, @@ -3743,7 +3703,7 @@ export default class MetamaskController extends EventEmitter { }), ); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) engine.push( createSnapMethodMiddleware(subjectType === SubjectType.Snap, { getUnlockPromise: this.appStateController.getUnlockPromise.bind( @@ -4241,7 +4201,7 @@ export default class MetamaskController extends EventEmitter { } }; - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) updateCaveat = (origin, target, caveatType, caveatValue) => { try { this.controllerMessenger.call( @@ -4308,7 +4268,9 @@ export default class MetamaskController extends EventEmitter { if (transactionSecurityCheckEnabled) { const chainId = Number( - hexToDecimal(this.networkController.store.getState().provider.chainId), + hexToDecimal( + this.networkController.store.getState().providerConfig.chainId, + ), ); try { diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index af2e5c62f..f5cf0ddaa 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -116,7 +116,7 @@ const MAINNET_CHAIN_ID = '0x1'; const firstTimeState = { config: {}, NetworkController: { - provider: { + providerConfig: { type: NETWORK_TYPES.RPC, rpcUrl: ALT_MAINNET_RPC_URL, chainId: MAINNET_CHAIN_ID, diff --git a/app/scripts/migrations/086.test.js b/app/scripts/migrations/086.test.js new file mode 100644 index 000000000..f38f0444d --- /dev/null +++ b/app/scripts/migrations/086.test.js @@ -0,0 +1,88 @@ +import { migrate, version } from './086'; + +jest.mock('uuid', () => { + const actual = jest.requireActual('uuid'); + + return { + ...actual, + v4: jest.fn(), + }; +}); + +describe('migration #86', () => { + it('should update the version metadata', async () => { + const oldStorage = { + meta: { + version: 85, + }, + data: {}, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.meta).toStrictEqual({ + version, + }); + }); + + it('should return state unaltered if there is no network controller state', async () => { + const oldData = { + other: 'data', + }; + const oldStorage = { + meta: { + version: 85, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should return state unaltered if there is no network controller provider state', async () => { + const oldData = { + other: 'data', + NetworkController: { + networkConfigurations: { + foo: 'bar', + }, + }, + }; + const oldStorage = { + meta: { + version: 85, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual(oldData); + }); + + it('should rename the provider config state', async () => { + const oldData = { + other: 'data', + NetworkController: { + provider: { + some: 'provider', + }, + }, + }; + const oldStorage = { + meta: { + version: 85, + }, + data: oldData, + }; + + const newStorage = await migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + other: 'data', + NetworkController: { + providerConfig: { + some: 'provider', + }, + }, + }); + }); +}); diff --git a/app/scripts/migrations/086.ts b/app/scripts/migrations/086.ts new file mode 100644 index 000000000..c4b60e270 --- /dev/null +++ b/app/scripts/migrations/086.ts @@ -0,0 +1,41 @@ +import { hasProperty, isObject } from '@metamask/utils'; +import { cloneDeep } from 'lodash'; + +export const version = 86; + +/** + * Rename network controller `provider` state to `providerConfig`. + * + * @param originalVersionedData - Versioned MetaMask extension state, exactly what we persist to dist. + * @param originalVersionedData.meta - State metadata. + * @param originalVersionedData.meta.version - The current state version. + * @param originalVersionedData.data - The persisted MetaMask state, keyed by controller. + * @returns Updated versioned MetaMask extension state. + */ +export async function migrate(originalVersionedData: { + meta: { version: number }; + data: Record; +}) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + versionedData.data = transformState(versionedData.data); + return versionedData; +} + +function transformState(state: Record) { + if ( + hasProperty(state, 'NetworkController') && + isObject(state.NetworkController) && + hasProperty(state.NetworkController, 'provider') + ) { + const networkControllerState = state.NetworkController; + networkControllerState.providerConfig = networkControllerState.provider; + delete networkControllerState.provider; + + return { + ...state, + NetworkController: networkControllerState, + }; + } + return state; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 5cbe4ee04..acde4758b 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -89,6 +89,7 @@ import * as m082 from './082'; import * as m083 from './083'; import * as m084 from './084'; import * as m085 from './085'; +import * as m086 from './086'; const migrations = [ m002, @@ -175,6 +176,7 @@ const migrations = [ m083, m084, m085, + m086, ]; export default migrations; diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 1ac0c853e..c4d64af8f 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -194,7 +194,7 @@ export default class ExtensionPlatform { let message = `Transaction ${nonce} failed! ${ errorMessage || txMeta.err.message }`; - ///: BEGIN:ONLY_INCLUDE_IN(mmi) + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) if (isNaN(nonce)) { message = `Transaction failed! ${errorMessage || txMeta.err.message}`; } diff --git a/app/scripts/ui.js b/app/scripts/ui.js index 2ac1f8227..148ce0397 100644 --- a/app/scripts/ui.js +++ b/app/scripts/ui.js @@ -22,7 +22,7 @@ import { checkForLastErrorAndLog } from '../../shared/modules/browser-runtime.ut import { SUPPORT_LINK } from '../../shared/lib/ui-utils'; import { getErrorHtml, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) registerDesktopErrorActions, ///: END:ONLY_INCLUDE_IN } from '../../shared/lib/error-utils'; @@ -264,7 +264,7 @@ async function start() { ( err, store, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) backgroundConnection, ///: END:ONLY_INCLUDE_IN ) => { @@ -274,7 +274,7 @@ async function start() { 'troubleStarting', err, store, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) backgroundConnection, ///: END:ONLY_INCLUDE_IN ); @@ -302,7 +302,7 @@ async function start() { displayCriticalError( 'troubleStarting', err, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) undefined, backgroundConnection, ///: END:ONLY_INCLUDE_IN @@ -345,7 +345,7 @@ function initializeUi(activeTab, connectionStream, cb) { cb( err, null, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) backgroundConnection, ///: END:ONLY_INCLUDE_IN ); @@ -367,7 +367,7 @@ async function displayCriticalError( errorKey, err, metamaskState, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) backgroundConnection, ///: END:ONLY_INCLUDE_IN ) { @@ -375,14 +375,14 @@ async function displayCriticalError( errorKey, SUPPORT_LINK, metamaskState, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) err, ///: END:ONLY_INCLUDE_IN ); container.innerHTML = html; - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) registerDesktopErrorActions(backgroundConnection, browser); ///: END:ONLY_INCLUDE_IN diff --git a/builds.yml b/builds.yml new file mode 100644 index 000000000..fe455afbe --- /dev/null +++ b/builds.yml @@ -0,0 +1,214 @@ +# TODO(ritave): Add support for environments (/development/build/constants.js:@ENVIRONMENT) +# TODO(ritave): Add support for build targets (/development/build/constants.js:@BUILD_TARGETS) +# TODO(ritave): Warn if not all of declared variables have been defined / used + +# The priority order of variable definitions (most important to least important): +# ; ; .metamaskprodrc; .metamaskrc; builds.yml:.buildTypes..env; builds.yml:.features..env; builds.yml:.env + +# The build type to use when no build type provided in the cli +default: &default main + +# Declaration of build types +# Each build type is composed of features, env variables and assets. +# Also known as productFlavors in Android lingo +buildTypes: + main: + features: + - build-main + # Additional env variables that are specific to this build + env: + - INFURA_PROD_PROJECT_ID + - SEGMENT_PROD_WRITE_KEY + - INFURA_ENV_KEY_REF: INFURA_PROD_PROJECT_ID + - SEGMENT_WRITE_KEY_REF: SEGMENT_PROD_WRITE_KEY + + beta: + features: + - build-beta + env: + - INFURA_BETA_PROJECT_ID + - SEGMENT_BETA_WRITE_KEY + - INFURA_ENV_KEY_REF: INFURA_BETA_PROJECT_ID + - SEGMENT_WRITE_KEY_REF: SEGMENT_BETA_WRITE_KEY + # Modifies how the version is displayed. + # eg. instead of 10.25.0 -> 10.25.0-beta.2 + isPrerelease: true + # Folder which contains overrides to browser manifests + manifestOverrides: ./app/build-types/mmi/manifest/ + + flask: + # Code surrounded using code fences for that feature + # will not be removed + features: + - snaps + - desktop + - build-flask + env: + - INFURA_FLASK_PROJECT_ID + - SEGMENT_FLASK_WRITE_KEY + - ALLOW_LOCAL_SNAPS: true + - REQUIRE_SNAPS_ALLOWLIST: false + - SUPPORT_LINK: https://metamask-flask.zendesk.com/hc + - SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new + - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID + - SEGMENT_WRITE_KEY_REF: SEGMENT_FLASK_WRITE_KEY + isPrerelease: true + + desktop: + features: + - snaps + - desktop + - build-flask + env: + - INFURA_FLASK_PROJECT_ID + - SEGMENT_FLASK_WRITE_KEY + - ALLOW_LOCAL_SNAPS: true + - REQUIRE_SNAPS_ALLOWLIST: false + - SUPPORT_LINK: https://metamask-flask.zendesk.com/hc + - SUPPORT_REQUEST_LINK: https://metamask-flask.zendesk.com/hc/en-us/requests/new + - INFURA_ENV_KEY_REF: INFURA_FLASK_PROJECT_ID + - SEGMENT_WRITE_KEY_REF: SEGMENT_FLASK_WRITE_KEY + isPrerelease: true + + mmi: + features: + - build-mmi + env: + - INFURA_MMI_PROJECT_ID + - SEGMENT_MMI_WRITE_KEY + - INFURA_ENV_KEY_REF: INFURA_MMI_PROJECT_ID + - SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY + - SUPPORT_LINK: https://mmi-support.zendesk.com/hc/en-us + - SUPPORT_REQUEST_LINK: https://mmi-support.zendesk.com/hc/en-us/requests/new + # For some reason, MMI uses this type of versioning + # Leaving it on for backwards compatibility + isPrerelease: true + +# Build types are composed of a set of features. +# Each feature can have code fences that add new code +# as well declaring, defining and overriding env variables +features: + snaps: + # Each feature might have variables that only exist when built with that feature active + env: + # Whether to allow snaps from localhost - local://localhost:8080/snap.manifest.json + # Enabled in Flask, will be disabled in Main + - ALLOW_LOCAL_SNAPS + # Whether to verify that a snap can be installed using an allow list + - REQUIRE_SNAPS_ALLOWLIST + assets: + - ./{app,shared,ui}/**/snaps/** + desktop: + env: + - COMPATIBILITY_VERSION_EXTENSION: 1 + - DISABLE_WEB_SOCKET_ENCRYPTION: false + - SKIP_OTP_PAIRING_FLOW: false + - WEB_SOCKET_PORT: null + + ### + # Build Type code extensions. Things like different support links, warning pages, banners + ### + + build-main: + build-beta: + assets: + # Assets that will be copied + - src: ./app/build-types/beta/images/ + dest: images + # Assets that are exclusively included in this feature and ignored in others + # Supports globs + - ./{app,shared,ui}/**/beta/** + build-mmi: + assets: + - src: ./app/build-types/mmi/images/ + dest: images + - ./{app,shared,ui}/**/mmi/** + build-flask: + assets: + - src: ./app/build-types/flask/images/ + dest: images + - ./{app,shared,ui}/**/flask/** + +# Env variables that are required for all types of builds +# +# env object supports both declarations (- FOO), and definitions (- FOO: BAR). +# Variables that were declared have to be defined somewhere in the load chain before usage +env: + - SWAPS_USE_DEV_APIS: false + - PORTFOLIO_URL: https://portfolio.metamask.io + - TOKEN_ALLOWANCE_IMPROVEMENTS: false + - TRANSACTION_SECURITY_PROVIDER: false + # The unlock password + - PASSWORD: null + # Also see METAMASK_DEBUG and NODE_DEBUG + - DEBUG: null + - SUPPORT_LINK: https://support.metamask.io + - SUPPORT_REQUEST_LINK: https://metamask.zendesk.com/hc/en-us + - SKIP_BACKGROUND_INITIALIZATION: false + - MULTICHAIN: false + + # TODO(ritave): Move ManifestV3 into a feature? + - ENABLE_MV3: false + - HARDWARE_WALLETS_MV3: false + # These are exclusively used for MV3 + - APPLY_LAVAMOAT + - FILE_NAMES + + ### + # API keys to 3rd party services + ### + + - PUBNUB_PUB_KEY: null + - PUBNUB_SUB_KEY: null + - SEGMENT_HOST: null + - SENTRY_DSN: null + - SENTRY_DSN_DEV: null + - OPENSEA_KEY: null + - ETHERSCAN_KEY: null + # also INFURA_PROJECT_ID below + + ### + # Build system backwards compatibility + ### + + - INFURA_ENV_KEY_REF + - SEGMENT_WRITE_KEY_REF + + ### + # Variables that are modified with hardcoded code + ### + + # Used for debugging changes to the phishing warning page. + # Modified in /development/build/scripts.js:@getPhishingWarningPageUrl + - PHISHING_WARNING_PAGE_URL: null + # Modified in /development/build/scripts.js:@getInfuraProjectId + - INFURA_PROJECT_ID + # Modified in /development/build/scripts.js:@getSegmentWriteKey + - SEGMENT_WRITE_KEY: '' + # Modified in /development/build/scripts.js:@setEnvironmentVariables + # Also see DEBUG and NODE_DEBUG + - METAMASK_DEBUG: false + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - ICON_NAMES + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - IN_TEST + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_ENVIRONMENT + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_VERSION + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - METAMASK_BUILD_TYPE + # Modified in /development/build/scripts.js:@setEnvironmentVariables + - NODE_ENV + # Defined by node itself + # For the purposes of the build system we define it as empty below + # if it's not inside process.env + # Also see DEBUG and METAMASK_DEBUG + - NODE_DEBUG: '' + + ### + # Meta variables + ### + + # Uses yaml anchors to DRY - https://juju.is/docs/sdk/yaml-anchors-and-aliases + - METAMASK_BUILD_TYPE_DEFAULT: *default diff --git a/coverage-targets.js b/coverage-targets.js index c78857661..cdd58d0f8 100644 --- a/coverage-targets.js +++ b/coverage-targets.js @@ -6,10 +6,10 @@ // subset of files to check against these targets. module.exports = { global: { - lines: 69.3, - branches: 57, - statements: 68.5, - functions: 61.5, + lines: 70.26, + branches: 57.91, + statements: 69.59, + functions: 62.97, }, transforms: { branches: 100, diff --git a/development/build/config.js b/development/build/config.js index b7b0f984c..d8a339de2 100644 --- a/development/build/config.js +++ b/development/build/config.js @@ -1,125 +1,157 @@ const path = require('path'); const { readFile } = require('fs/promises'); +const assert = require('assert'); +const { AssertionError } = require('assert'); const ini = require('ini'); -const { BuildType } = require('../lib/build-type'); +const { loadBuildTypesConfig } = require('../lib/build-type'); +const { Variables } = require('../lib/variables'); +const { ENVIRONMENT } = require('./constants'); -const configurationPropertyNames = [ - 'MULTICHAIN', - 'INFURA_PROJECT_ID', - 'PHISHING_WARNING_PAGE_URL', - 'PORTFOLIO_URL', - 'SEGMENT_HOST', - 'SEGMENT_WRITE_KEY', - 'SENTRY_DSN_DEV', - 'SWAPS_USE_DEV_APIS', - // Desktop - 'COMPATIBILITY_VERSION_EXTENSION', - 'DISABLE_WEB_SOCKET_ENCRYPTION', - 'METAMASK_DEBUG', - 'SKIP_OTP_PAIRING_FLOW', - 'ENABLE_MV3', -]; +const VARIABLES_REQUIRED_IN_PRODUCTION = { + main: ['INFURA_PROD_PROJECT_ID', 'SEGMENT_PROD_WRITE_KEY', 'SENTRY_DSN'], + beta: ['INFURA_BETA_PROJECT_ID', 'SEGMENT_BETA_WRITE_KEY', 'SENTRY_DSN'], + flask: ['INFURA_FLASK_PROJECT_ID', 'SEGMENT_FLASK_WRITE_KEY', 'SENTRY_DSN'], +}; -const productionConfigurationPropertyNames = [ - 'INFURA_BETA_PROJECT_ID', - 'INFURA_FLASK_PROJECT_ID', - 'INFURA_PROD_PROJECT_ID', - 'SEGMENT_BETA_WRITE_KEY', - 'SEGMENT_FLASK_WRITE_KEY', - 'SEGMENT_PROD_WRITE_KEY', - 'SENTRY_DSN', -]; - -/** - * Get configuration for non-production builds. - * - * @returns {object} The production configuration. - */ -async function getConfig() { - const configPath = path.resolve(__dirname, '..', '..', '.metamaskrc'); +async function fromIniFile(filepath) { let configContents = ''; try { - configContents = await readFile(configPath, { + configContents = await readFile(filepath, { encoding: 'utf8', }); } catch (error) { if (error.code !== 'ENOENT') { throw error; } + return undefined; } - const environmentVariables = {}; - for (const propertyName of configurationPropertyNames) { - if (process.env[propertyName]) { - environmentVariables[propertyName] = process.env[propertyName]; + const variables = ini.parse(configContents); + assert( + !Object.values(variables).some((variable) => typeof variable === 'object'), + `When loading ${filepath} - INI categories are not supported`, + ); + const entries = Object.entries(variables); + + const declarations = new Set( + entries.filter(([, value]) => value === '').map(([key]) => key), + ); + const definitions = new Map( + entries + .filter(([, value]) => value !== '') + .map(([key, value]) => [key, value]), + ); + + return { declarations, definitions }; +} + +function fromEnv(declarations) { + const definitions = new Map( + [...declarations] + .filter((declaration) => declaration in process.env) + .map((declaration) => [declaration, process.env[declaration]]), + ); + return { definitions, declarations: new Set() }; +} + +function fromBuildsYML(buildType, config) { + const extractDeclarations = (envArray) => + envArray === undefined + ? [] + : envArray.map((env) => (typeof env === 'string' ? env : env.key)); + const extractDefinitions = (envArray) => + envArray === undefined + ? [] + : envArray.filter((env) => typeof env !== 'string'); + + // eslint-disable-next-line no-param-reassign + buildType = buildType ?? config.default; + const activeBuild = config.buildTypes[buildType]; + const activeFeatures = activeBuild.features ?? []; + + let declarations = [...extractDeclarations(config.env)]; + + activeFeatures + .map((feature) => config.features[feature]) + .filter((feature) => feature !== null) + .forEach(({ env }) => declarations.push(...extractDeclarations(env))); + + declarations.push(...extractDeclarations(activeBuild.env)); + declarations = new Set(declarations); + + const definitions = new Map(); + + // 1. root env + extractDefinitions(config.env).forEach(({ key, value }) => + definitions.set(key, value), + ); + // 2. features env + activeFeatures + .filter((key) => config.features[key] !== null) + .map((key) => config.features[key].env) + .map(extractDefinitions) + .flat() + .forEach(({ key, value }) => definitions.set(key, value)); + // 3. build type env + extractDefinitions(activeBuild.env).forEach(({ key, value }) => + definitions.set(key, value), + ); + + return { declarations, definitions, activeFeatures, activeBuild }; +} + +/** + * + * @param {string?} buildType - The chosen build type to build + * @param environment + * @returns Parsed configuration of the build pipeline + */ +async function getConfig(buildType, environment) { + const config = loadBuildTypesConfig(); + const { + declarations: ymlDeclarations, + definitions: ymlDefinitions, + activeBuild, + activeFeatures, + } = await fromBuildsYML(buildType, config); + + const variables = new Variables(ymlDeclarations); + + // notice that maps have inverted value and key pair in forEach + ymlDefinitions.forEach((value, key) => variables.set(key, value)); + + ( + await fromIniFile(path.resolve(__dirname, '..', '..', '.metamaskrc')) + )?.definitions.forEach((value, key) => variables.set(key, value)); + ( + await fromIniFile(path.resolve(__dirname, '..', '..', '.metamaskprodrc')) + )?.definitions.forEach((value, key) => variables.set(key, value)); + + fromEnv(ymlDeclarations).definitions.forEach((value, key) => + variables.set(key, value), + ); + + // TODO(ritave): Move build targets and environments to builds.yml + if (environment === ENVIRONMENT.PRODUCTION) { + const undefinedVariables = VARIABLES_REQUIRED_IN_PRODUCTION[ + buildType + ].filter((variable) => !variables.isDefined(variable)); + if (undefinedVariables.length !== 0) { + const message = `Some variables required to build production target are not defined. + - ${undefinedVariables.join('\n - ')} +`; + throw new AssertionError({ message }); } } return { - ...ini.parse(configContents), - ...environmentVariables, + variables, + activeBuild, + activeFeatures, + buildsYml: config, }; } -/** - * Get configuration for production builds and perform validation. - * - * This function validates that all required variables are present, and that - * the production configuration file doesn't include any extraneous entries. - * - * @param {BuildType} buildType - The current build type (e.g. "main", "flask", - * etc.). - * @returns {object} The production configuration. - */ -async function getProductionConfig(buildType) { - const prodConfigPath = path.resolve(__dirname, '..', '..', '.metamaskprodrc'); - let prodConfigContents = ''; - try { - prodConfigContents = await readFile(prodConfigPath, { - encoding: 'utf8', - }); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } - } - - const environmentVariables = {}; - for (const propertyName of productionConfigurationPropertyNames) { - if (process.env[propertyName]) { - environmentVariables[propertyName] = process.env[propertyName]; - } - } - - const prodConfig = { - ...ini.parse(prodConfigContents), - ...environmentVariables, - }; - - const requiredEnvironmentVariables = { - all: ['SENTRY_DSN'], - [BuildType.beta]: ['INFURA_BETA_PROJECT_ID', 'SEGMENT_BETA_WRITE_KEY'], - [BuildType.flask]: ['INFURA_FLASK_PROJECT_ID', 'SEGMENT_FLASK_WRITE_KEY'], - [BuildType.main]: ['INFURA_PROD_PROJECT_ID', 'SEGMENT_PROD_WRITE_KEY'], - [BuildType.mmi]: ['INFURA_MMI_PROJECT_ID', 'SEGMENT_MMI_WRITE_KEY'], - }; - - for (const required of [ - ...requiredEnvironmentVariables.all, - ...requiredEnvironmentVariables[buildType], - ]) { - if (!prodConfig[required]) { - throw new Error(`Missing '${required}' environment variable`); - } - } - - const allValid = Object.values(requiredEnvironmentVariables).flat(); - for (const environmentVariable of Object.keys(prodConfig)) { - if (!allValid.includes(environmentVariable)) { - throw new Error(`Invalid environment variable: '${environmentVariable}'`); - } - } - return prodConfig; -} - -module.exports = { getConfig, getProductionConfig }; +module.exports = { + getConfig, +}; diff --git a/development/build/etc.js b/development/build/etc.js index 3da86409f..0479f5eee 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -6,7 +6,7 @@ const del = require('del'); const pify = require('pify'); const pump = pify(require('pump')); -const { BuildType } = require('../lib/build-type'); +const { loadBuildTypesConfig } = require('../lib/build-type'); const { TASKS } = require('./constants'); const { createTask, composeParallel } = require('./task'); @@ -42,7 +42,7 @@ function createEtcTasks({ browserPlatforms, buildType, livereload, version }) { function createZipTask(platform, buildType, version) { return async () => { const path = - buildType === BuildType.main + buildType === loadBuildTypesConfig().default ? `metamask-${platform}-${version}` : `metamask-${buildType}-${platform}-${version}`; await pump( diff --git a/development/build/index.js b/development/build/index.js index dfa5d4652..b9d00698a 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -10,9 +10,11 @@ const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); const { sync: globby } = require('globby'); const lavapack = require('@lavamoat/lavapack'); +const difference = require('lodash/difference'); +const { intersection } = require('lodash'); const { getVersion } = require('../lib/get-version'); -const { BuildType, BuildTypeInheritance } = require('../lib/build-type'); -const { TASKS, ENVIRONMENT } = require('./constants'); +const { loadBuildTypesConfig } = require('../lib/build-type'); +const { TASKS } = require('./constants'); const { createTask, composeSeries, @@ -25,7 +27,7 @@ const createStyleTasks = require('./styles'); const createStaticAssetTasks = require('./static'); const createEtcTasks = require('./etc'); const { getBrowserVersionMap, getEnvironment } = require('./utils'); -const { getConfig, getProductionConfig } = require('./config'); +const { getConfig } = require('./config'); const { BUILD_TARGETS } = require('./constants'); // Packages required dynamically via browserify configuration in dependencies @@ -74,61 +76,67 @@ async function defineAndRunBuildTasks() { platform, } = await parseArgv(); - // scuttle on production/tests environment only - const shouldScuttle = ['dist', 'prod', 'test'].includes(entryTask); + const isRootTask = ['dist', 'prod', 'test', 'dev'].includes(entryTask); - console.log( - `Building lavamoat runtime file`, - `(scuttling is ${shouldScuttle ? 'on' : 'off'})`, - ); + if (isRootTask) { + // scuttle on production/tests environment only + const shouldScuttle = ['dist', 'prod', 'test'].includes(entryTask); - // build lavamoat runtime file - await lavapack.buildRuntime({ - scuttleGlobalThis: applyLavaMoat && shouldScuttle, - scuttleGlobalThisExceptions: [ - // globals used by different mm deps outside of lm compartment - 'toString', - 'getComputedStyle', - 'addEventListener', - 'removeEventListener', - 'ShadowRoot', - 'HTMLElement', - 'Element', - 'pageXOffset', - 'pageYOffset', - 'visualViewport', - 'Reflect', - 'Set', - 'Object', - 'navigator', - 'harden', - 'console', - 'Image', // Used by browser to generate notifications - // globals chrome driver needs to function (test env) - /cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu, - 'performance', - 'parseFloat', - 'innerWidth', - 'innerHeight', - 'Symbol', - 'Math', - 'DOMRect', - 'Number', - 'Array', - 'crypto', - 'Function', - 'Uint8Array', - 'String', - 'Promise', - // globals sentry needs to function - '__SENTRY__', - 'appState', - 'extra', - 'stateHooks', - 'sentryHooks', - 'sentry', - ], - }); + console.log( + `Building lavamoat runtime file`, + `(scuttling is ${shouldScuttle ? 'on' : 'off'})`, + ); + + // build lavamoat runtime file + await lavapack.buildRuntime({ + scuttleGlobalThis: applyLavaMoat && shouldScuttle, + scuttleGlobalThisExceptions: [ + // globals used by different mm deps outside of lm compartment + 'toString', + 'getComputedStyle', + 'addEventListener', + 'removeEventListener', + 'ShadowRoot', + 'HTMLElement', + 'Element', + 'pageXOffset', + 'pageYOffset', + 'visualViewport', + 'Reflect', + 'Set', + 'Object', + 'navigator', + 'harden', + 'console', + 'Image', // Used by browser to generate notifications + // globals chrome driver needs to function (test env) + /cdc_[a-zA-Z0-9]+_[a-zA-Z]+/iu, + 'performance', + 'parseFloat', + 'innerWidth', + 'innerHeight', + 'Symbol', + 'Math', + 'DOMRect', + 'Number', + 'Array', + 'crypto', + 'Function', + 'Uint8Array', + 'String', + 'Promise', + 'JSON', + 'Date', + // globals sentry needs to function + '__SENTRY__', + 'appState', + 'extra', + 'stateHooks', + 'sentryHooks', + 'sentry', + ], + }); + } const browserPlatforms = platform ? [platform] : ['firefox', 'chrome']; @@ -272,9 +280,9 @@ testDev: Create an unoptimized, live-reloading build for debugging e2e tests.`, type: 'boolean', }) .option('build-type', { - default: BuildType.main, + default: loadBuildTypesConfig().default, description: 'The type of build to create.', - choices: Object.keys(BuildType), + choices: Object.keys(loadBuildTypesConfig().buildTypes), }) .option('build-version', { default: 0, @@ -354,13 +362,8 @@ testDev: Create an unoptimized, live-reloading build for debugging e2e tests.`, const highLevelTasks = Object.values(BUILD_TARGETS); if (highLevelTasks.includes(task)) { const environment = getEnvironment({ buildTarget: task }); - if (environment === ENVIRONMENT.PRODUCTION) { - // Output ignored, this is only called to ensure config is validated - await getProductionConfig(buildType); - } else { - // Output ignored, this is only called to ensure config is validated - await getConfig(); - } + // Output ignored, this is only called to ensure config is validated + await getConfig(buildType, environment); } return { @@ -386,29 +389,36 @@ testDev: Create an unoptimized, live-reloading build for debugging e2e tests.`, * build, or `null` if no files are to be ignored. */ function getIgnoredFiles(currentBuildType) { - const inheritedBuildTypes = BuildTypeInheritance[currentBuildType] || []; - const excludedFiles = Object.values(BuildType) - // This filter removes "main" and the current build type. The files of any - // build types that remain in the array will be excluded. "main" is the - // default build type, and has no files that are excluded from other builds. - .filter( - (buildType) => - buildType !== BuildType.main && - buildType !== currentBuildType && - !inheritedBuildTypes.includes(buildType), - ) - // Compute globs targeting files for exclusion for each excluded build - // type. - .reduce((excludedGlobs, excludedBuildType) => { - return excludedGlobs.concat([ - `../../app/**/${excludedBuildType}/**`, - `../../shared/**/${excludedBuildType}/**`, - `../../ui/**/${excludedBuildType}/**`, - ]); - }, []) - // This creates absolute paths of the form: - // PATH_TO_REPOSITORY_ROOT/app/**/${excludedBuildType}/** - .map((pathGlob) => path.resolve(__dirname, pathGlob)); + const buildConfig = loadBuildTypesConfig(); + const cwd = process.cwd(); - return globby(excludedFiles); + const exclusiveAssetsForFeatures = (features) => + globby( + features + .flatMap( + (feature) => + buildConfig.features[feature].assets + ?.filter((asset) => 'exclusiveInclude' in asset) + .map((asset) => asset.exclusiveInclude) ?? [], + ) + .map((pathGlob) => path.resolve(cwd, pathGlob)), + ); + + const allFeatures = Object.keys(buildConfig.features); + const activeFeatures = + buildConfig.buildTypes[currentBuildType].features ?? []; + const inactiveFeatures = difference(allFeatures, activeFeatures); + + const ignoredPaths = exclusiveAssetsForFeatures(inactiveFeatures); + // We do a sanity check to verify that any inactive feature haven't excluded files + // that active features are trying to include + const activePaths = exclusiveAssetsForFeatures(activeFeatures); + const conflicts = intersection(activePaths, ignoredPaths); + if (conflicts.length !== 0) { + throw new Error(`Below paths are required exclusively by both active and inactive features resulting in a conflict: +\t-> ${conflicts.join('\n\t-> ')} +Please fix builds.yml`); + } + + return ignoredPaths; } diff --git a/development/build/manifest.js b/development/build/manifest.js index e95690868..6d240dbfa 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -6,7 +6,7 @@ const { mergeWith, cloneDeep, capitalize } = require('lodash'); const baseManifest = process.env.ENABLE_MV3 ? require('../../app/manifest/v3/_base.json') : require('../../app/manifest/v2/_base.json'); -const { BuildType } = require('../lib/build-type'); +const { loadBuildTypesConfig } = require('../lib/build-type'); const { TASKS, ENVIRONMENT } = require('./constants'); const { createTask, composeSeries } = require('./task'); @@ -165,25 +165,24 @@ async function writeJson(obj, file) { * Get manifest modifications for the given build type, including modifications specific to the * given platform. * - * @param {BuildType} buildType - The build type. + * @param {string} buildType - The build type. * @param {string} platform - The platform (i.e. the browser). - * @returns {object} The build modificantions for the given build type and platform. + * @returns {object} The build modifications for the given build type and platform. */ async function getBuildModifications(buildType, platform) { - if (!Object.values(BuildType).includes(buildType)) { + const buildConfig = loadBuildTypesConfig(); + if (!(buildType in buildConfig.buildTypes)) { throw new Error(`Invalid build type: ${buildType}`); - } else if (buildType === BuildType.main) { + } + + const overridesPath = buildConfig.buildTypes[buildType].manifestOverrides; + if (overridesPath === undefined) { return {}; } const builtTypeManifestDirectoryPath = path.resolve( - __dirname, - '..', - '..', - 'app', - 'build-types', - buildType, - 'manifest', + process.cwd(), + overridesPath, ); const baseBuildTypeModificationsPath = path.join( diff --git a/development/build/scripts.js b/development/build/scripts.js index 3be5a912f..8f65f863c 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -1,7 +1,10 @@ +// TODO(ritave): Remove switches on hardcoded build types + const { callbackify } = require('util'); const path = require('path'); const { writeFileSync, readFileSync } = require('fs'); const EventEmitter = require('events'); +const assert = require('assert'); const gulp = require('gulp'); const watch = require('gulp-watch'); const Vinyl = require('vinyl'); @@ -24,15 +27,15 @@ const Sqrl = require('squirrelly'); const lavapack = require('@lavamoat/lavapack'); const lavamoatBrowserify = require('lavamoat-browserify'); const terser = require('terser'); +const moduleResolver = require('babel-plugin-module-resolver'); const bifyModuleGroups = require('bify-module-groups'); const phishingWarningManifest = require('@metamask/phishing-warning/package.json'); const { streamFlatMap } = require('../stream-flat-map'); -const { BuildType } = require('../lib/build-type'); const { generateIconNames } = require('../generate-icon-names'); const { BUILD_TARGETS, ENVIRONMENT } = require('./constants'); -const { getConfig, getProductionConfig } = require('./config'); +const { getConfig } = require('./config'); const { isDevBuild, isTestBuild, @@ -101,67 +104,87 @@ const standardScuttlingConfig = { * Get the appropriate Infura project ID. * * @param {object} options - The Infura project ID options. - * @param {BuildType} options.buildType - The current build type. - * @param {object} options.config - The environment variable configuration. + * @param {string} options.buildType - The current build type. * @param {ENVIRONMENT[keyof ENVIRONMENT]} options.environment - The build environment. * @param {boolean} options.testing - Whether this is a test build or not. + * @param options.variables * @returns {string} The Infura project ID. */ -function getInfuraProjectId({ buildType, config, environment, testing }) { +function getInfuraProjectId({ buildType, variables, environment, testing }) { + const EMPTY_PROJECT_ID = '00000000000000000000000000000000'; if (testing) { - return '00000000000000000000000000000000'; + return EMPTY_PROJECT_ID; } else if (environment !== ENVIRONMENT.PRODUCTION) { // Skip validation because this is unset on PRs from forks. - return config.INFURA_PROJECT_ID; - } else if (buildType === BuildType.main) { - return config.INFURA_PROD_PROJECT_ID; - } else if (buildType === BuildType.beta) { - return config.INFURA_BETA_PROJECT_ID; - } else if (buildType === BuildType.flask) { - return config.INFURA_FLASK_PROJECT_ID; - } else if (buildType === BuildType.mmi) { - return config.INFURA_MMI_PROJECT_ID; + // For forks, return empty project ID if we don't have one. + if ( + !variables.isDefined('INFURA_PROJECT_ID') && + environment === ENVIRONMENT.PULL_REQUEST + ) { + return EMPTY_PROJECT_ID; + } + return variables.get('INFURA_PROJECT_ID'); } - throw new Error(`Invalid build type: '${buildType}'`); + /** @type {string|undefined} */ + const infuraKeyReference = variables.get('INFURA_ENV_KEY_REF'); + assert( + typeof infuraKeyReference === 'string' && infuraKeyReference.length > 0, + `Build type "${buildType}" has improperly set INFURA_ENV_KEY_REF in builds.yml. Current value: "${infuraKeyReference}"`, + ); + /** @type {string|undefined} */ + const infuraProjectId = variables.get(infuraKeyReference); + assert( + typeof infuraProjectId === 'string' && infuraProjectId.length > 0, + `Infura Project ID environmental variable "${infuraKeyReference}" is set improperly.`, + ); + return infuraProjectId; } /** * Get the appropriate Segment write key. * * @param {object} options - The Segment write key options. - * @param {BuildType} options.buildType - The current build type. - * @param {object} options.config - The environment variable configuration. + * @param {string} options.buildType - The current build type. * @param {keyof ENVIRONMENT} options.environment - The current build environment. + * @param {import('../lib/variables').Variables} options.variables - Object containing all variables that modify the build pipeline * @returns {string} The Segment write key. */ -function getSegmentWriteKey({ buildType, config, environment }) { +function getSegmentWriteKey({ buildType, variables, environment }) { if (environment !== ENVIRONMENT.PRODUCTION) { // Skip validation because this is unset on PRs from forks, and isn't necessary for development builds. - return config.SEGMENT_WRITE_KEY; - } else if (buildType === BuildType.main) { - return config.SEGMENT_PROD_WRITE_KEY; - } else if (buildType === BuildType.beta) { - return config.SEGMENT_BETA_WRITE_KEY; - } else if (buildType === BuildType.flask) { - return config.SEGMENT_FLASK_WRITE_KEY; - } else if (buildType === BuildType.mmi) { - return config.SEGMENT_MMI_WRITE_KEY; + return variables.get('SEGMENT_WRITE_KEY'); } - throw new Error(`Invalid build type: '${buildType}'`); + + const segmentKeyReference = variables.get('SEGMENT_WRITE_KEY_REF'); + assert( + typeof segmentKeyReference === 'string' && segmentKeyReference.length > 0, + `Build type "${buildType}" has improperly set SEGMENT_WRITE_KEY_REF in builds.yml. Current value: "${segmentKeyReference}"`, + ); + + const segmentWriteKey = variables.get(segmentKeyReference); + assert( + typeof segmentWriteKey === 'string' && segmentWriteKey.length > 0, + `Segment Write Key environmental variable "${segmentKeyReference}" is set improperly.`, + ); + return segmentWriteKey; } /** * Get the URL for the phishing warning page, if it has been set. * * @param {object} options - The phishing warning page options. - * @param {object} options.config - The environment variable configuration. * @param {boolean} options.testing - Whether this is a test build or not. + * @param {import('../lib/variables').Variables} options.variables - Object containing all variables that modify the build pipeline * @returns {string} The URL for the phishing warning page, or `undefined` if no URL is set. */ -function getPhishingWarningPageUrl({ config, testing }) { - let phishingWarningPageUrl = config.PHISHING_WARNING_PAGE_URL; +function getPhishingWarningPageUrl({ variables, testing }) { + let phishingWarningPageUrl = variables.get('PHISHING_WARNING_PAGE_URL'); - if (!phishingWarningPageUrl) { + assert( + phishingWarningPageUrl === null || + typeof phishingWarningPageUrl === 'string', + ); + if (phishingWarningPageUrl === null) { phishingWarningPageUrl = testing ? 'http://localhost:9999/' : `https://metamask.github.io/phishing-warning/v${phishingWarningManifest.version}/`; @@ -209,7 +232,7 @@ module.exports = createScriptTasks; * LavaMoat at runtime or not. * @param {string[]} options.browserPlatforms - A list of browser platforms to * build bundles for. - * @param {BuildType} options.buildType - The current build type (e.g. "main", + * @param {string} options.buildType - The current build type (e.g. "main", * "flask", etc.). * @param {string[] | null} options.ignoredFiles - A list of files to exclude * from the current build. @@ -455,7 +478,7 @@ function createScriptTasks({ * @param {string[]} options.browserPlatforms - A list of browser platforms to * build bundles for. * @param {BUILD_TARGETS} options.buildTarget - The current build target. - * @param {BuildType} options.buildType - The current build type (e.g. "main", + * @param {string} options.buildType - The current build type (e.g. "main", * "flask", etc.). * @param {string[] | null} options.ignoredFiles - A list of files to exclude * from the current build. @@ -541,7 +564,7 @@ async function createManifestV3AppInitializationBundle({ * @param {string[]} options.browserPlatforms - A list of browser platforms to * build bundles for. * @param {BUILD_TARGETS} options.buildTarget - The current build target. - * @param {BuildType} options.buildType - The current build type (e.g. "main", + * @param {string} options.buildType - The current build type (e.g. "main", * "flask", etc.). * @param {string[]} options.entryFiles - A list of entry point file paths, * relative to the repository root directory. @@ -576,18 +599,29 @@ function createFactoredBuild({ const reloadOnChange = isDevBuild(buildTarget); const minify = !isDevBuild(buildTarget); - const envVars = await getEnvironmentVariables({ + const environment = getEnvironment({ buildTarget }); + const config = await getConfig(buildType, environment); + const { variables, activeBuild } = config; + await setEnvironmentVariables({ buildTarget, buildType, + environment, + variables, + activeBuild, version, }); + const features = { + active: new Set(activeBuild.features ?? []), + all: new Set(Object.keys(config.buildsYml.features)), + }; setupBundlerDefaults(buildConfiguration, { buildTarget, - buildType, - envVars, + variables, + envVars: buildSafeVariableObject(variables), ignoredFiles, policyOnly, minify, + features, reloadOnChange, shouldLintFenceFiles, }); @@ -760,7 +794,7 @@ function createFactoredBuild({ * @param {string[]} options.browserPlatforms - A list of browser platforms to * build the bundle for. * @param {BUILD_TARGETS} options.buildTarget - The current build target. - * @param {BuildType} options.buildType - The current build type (e.g. "main", + * @param {string} options.buildType - The current build type (e.g. "main", * "flask", etc.). * @param {string} options.destFilepath - The file path the bundle should be * written to. @@ -806,20 +840,31 @@ function createNormalBundle({ const reloadOnChange = Boolean(devMode); const minify = Boolean(devMode) === false; - const envVars = { - ...(await getEnvironmentVariables({ - buildTarget, - buildType, - version, - })), - ...extraEnvironmentVariables, + const environment = getEnvironment({ buildTarget }); + const config = await getConfig(buildType, environment); + const { activeBuild, variables } = config; + await setEnvironmentVariables({ + buildTarget, + buildType, + variables, + environment, + activeBuild, + version, + }); + Object.entries(extraEnvironmentVariables ?? {}).forEach(([key, value]) => + variables.set(key, value), + ); + + const features = { + active: new Set(activeBuild.features ?? []), + all: new Set(Object.keys(config.buildsYml.features)), }; setupBundlerDefaults(buildConfiguration, { - buildType, - envVars, + envVars: buildSafeVariableObject(variables), ignoredFiles, policyOnly, minify, + features, reloadOnChange, shouldLintFenceFiles, applyLavaMoat, @@ -865,11 +910,11 @@ function setupBundlerDefaults( buildConfiguration, { buildTarget, - buildType, envVars, ignoredFiles, policyOnly, minify, + features, reloadOnChange, shouldLintFenceFiles, applyLavaMoat, @@ -878,26 +923,36 @@ function setupBundlerDefaults( const { bundlerOpts } = buildConfiguration; const extensions = ['.js', '.ts', '.tsx']; + const isSnapsFlask = + features.active.has('snaps') && features.active.has('build-flask'); + Object.assign(bundlerOpts, { // Source transforms transform: [ // // Remove code that should be excluded from builds of the current type - createRemoveFencedCodeTransform(buildType, shouldLintFenceFiles), + createRemoveFencedCodeTransform(features, shouldLintFenceFiles), // Transpile top-level code [ babelify, // Run TypeScript files through Babel - { extensions }, - ], - // Transpile libraries that use ES2020 unsupported by Chrome v78 - [ - babelify, { - only: [ - './**/node_modules/@ethereumjs/util', - './**/node_modules/superstruct', - ], - global: true, + extensions, + plugins: isSnapsFlask + ? [ + [ + moduleResolver, + { + alias: { + '@metamask/snaps-controllers': + '@metamask/snaps-controllers-flask', + '@metamask/snaps-ui': '@metamask/snaps-ui-flask', + '@metamask/snaps-utils': '@metamask/snaps-utils-flask', + '@metamask/rpc-methods': '@metamask/rpc-methods-flask', + }, + }, + ], + ] + : [], }, ], // Inline `fs.readFileSync` files @@ -1085,6 +1140,11 @@ async function createBundle(buildConfiguration, { reloadOnChange }) { logError(error); process.exit(1); }); + pipeline.on('error', (error) => { + console.error('Pipeline failed! See details below.'); + logError(error); + process.exit(1); + }); } // trigger build pipeline instrumentations events.emit('configurePipeline', { pipeline, bundleStream }); @@ -1101,56 +1161,55 @@ async function createBundle(buildConfiguration, { reloadOnChange }) { } /** - * Get environment variables to inject in the current build. + * Sets environment variables to inject in the current build. * * @param {object} options - Build options. * @param {BUILD_TARGETS} options.buildTarget - The current build target. - * @param {BuildType} options.buildType - The current build type (e.g. "main", + * @param {string} options.buildType - The current build type (e.g. "main", * "flask", etc.). * @param {string} options.version - The current version of the extension. - * @returns {object} A map of environment variables to inject. + * @param options.activeBuild + * @param options.variables + * @param options.environment */ -async function getEnvironmentVariables({ buildTarget, buildType, version }) { - const environment = getEnvironment({ buildTarget }); - const config = - environment === ENVIRONMENT.PRODUCTION - ? await getProductionConfig(buildType) - : await getConfig(); - +async function setEnvironmentVariables({ + buildTarget, + buildType, + activeBuild, + environment, + variables, + version, +}) { const devMode = isDevBuild(buildTarget); const testing = isTestBuild(buildTarget); const iconNames = await generateIconNames(); - return { + + variables.set({ ICON_NAMES: iconNames, - MULTICHAIN: config.MULTICHAIN === '1', - CONF: devMode ? config : {}, - ENABLE_MV3: config.ENABLE_MV3, IN_TEST: testing, INFURA_PROJECT_ID: getInfuraProjectId({ buildType, - config, + activeBuild, + variables, environment, testing, }), - METAMASK_DEBUG: devMode || config.METAMASK_DEBUG === '1', + METAMASK_DEBUG: devMode || variables.getMaybe('METAMASK_DEBUG') === true, METAMASK_ENVIRONMENT: environment, METAMASK_VERSION: version, METAMASK_BUILD_TYPE: buildType, NODE_ENV: devMode ? ENVIRONMENT.DEVELOPMENT : ENVIRONMENT.PRODUCTION, - PHISHING_WARNING_PAGE_URL: getPhishingWarningPageUrl({ config, testing }), - PORTFOLIO_URL: config.PORTFOLIO_URL || 'https://portfolio.metamask.io', - SEGMENT_HOST: config.SEGMENT_HOST, - SEGMENT_WRITE_KEY: getSegmentWriteKey({ buildType, config, environment }), - SENTRY_DSN: config.SENTRY_DSN, - SENTRY_DSN_DEV: config.SENTRY_DSN_DEV, - SWAPS_USE_DEV_APIS: config.SWAPS_USE_DEV_APIS === '1', - TOKEN_ALLOWANCE_IMPROVEMENTS: config.TOKEN_ALLOWANCE_IMPROVEMENTS === '1', - TRANSACTION_SECURITY_PROVIDER: config.TRANSACTION_SECURITY_PROVIDER === '1', - // Desktop - COMPATIBILITY_VERSION_EXTENSION: config.COMPATIBILITY_VERSION_EXTENSION, - DISABLE_WEB_SOCKET_ENCRYPTION: config.DISABLE_WEB_SOCKET_ENCRYPTION === '1', - SKIP_OTP_PAIRING_FLOW: config.SKIP_OTP_PAIRING_FLOW === '1', - }; + PHISHING_WARNING_PAGE_URL: getPhishingWarningPageUrl({ + variables, + testing, + }), + SEGMENT_WRITE_KEY: getSegmentWriteKey({ + buildType, + activeBuild, + variables, + environment, + }), + }); } function renderHtmlFile({ @@ -1183,6 +1242,29 @@ function renderHtmlFile({ }); } +/** + * Builds a javascript object that throws an error when trying to access a property that wasn't defined properly + * + * @param {Variables} variables + * @returns {{[key: string]: unknown }} Variable definitions + */ +function buildSafeVariableObject(variables) { + return new Proxy( + {}, + { + has(_, key) { + return key !== '_'; // loose-envify uses "_" for settings + }, + get(_, key) { + if (key === '_') { + return undefined; // loose-envify uses "_" for settings + } + return variables.get(key); + }, + }, + ); +} + function beep() { process.stdout.write('\x07'); } diff --git a/development/build/static.js b/development/build/static.js index 15fa0f06c..644105c87 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -4,7 +4,7 @@ const watch = require('gulp-watch'); const glob = require('fast-glob'); const locales = require('../../app/_locales/index.json'); -const { BuildType } = require('../lib/build-type'); +const { loadBuildTypesConfig } = require('../lib/build-type'); const { TASKS } = require('./constants'); const { createTask, composeSeries } = require('./task'); @@ -31,41 +31,23 @@ module.exports = function createStaticAssetTasks({ copyTargetsDevs[browser] = copyTargetsDev; }); - const additionalBuildTargets = { - [BuildType.beta]: [ - { - src: './app/build-types/beta/images/', - dest: `images`, - }, - ], - [BuildType.flask]: [ - { - src: './app/build-types/flask/images/', - dest: `images`, - }, - ], - [BuildType.desktop]: [ - { - src: './app/build-types/desktop/images/', - dest: `images`, - }, - ], - [BuildType.mmi]: [ - { - src: './app/build-types/mmi/images/', - dest: `images`, - }, - ], - }; + const buildConfig = loadBuildTypesConfig(); - if (Object.keys(additionalBuildTargets).includes(buildType)) { - Object.entries(copyTargetsProds).forEach(([_, copyTargetsProd]) => - copyTargetsProd.push(...additionalBuildTargets[buildType]), - ); - Object.entries(copyTargetsDevs).forEach(([_, copyTargetsDev]) => - copyTargetsDev.push(...additionalBuildTargets[buildType]), - ); - } + const activeFeatures = buildConfig.buildTypes[buildType].features ?? []; + + const additionalAssets = activeFeatures.flatMap( + (feature) => + buildConfig.features[feature].assets?.filter( + (asset) => !('exclusiveInclude' in asset), + ) ?? [], + ); + + Object.entries(copyTargetsProds).forEach(([_, copyTargetsProd]) => + copyTargetsProd.push(...additionalAssets), + ); + Object.entries(copyTargetsDevs).forEach(([_, copyTargetsDev]) => + copyTargetsDev.push(...additionalAssets), + ); const prodTasks = []; Object.entries(copyTargetsProds).forEach(([browser, copyTargetsProd]) => { @@ -120,7 +102,7 @@ module.exports = function createStaticAssetTasks({ await Promise.all( sources.map(async (src) => { const relativePath = path.relative(baseDir, src); - await fs.copy(src, `${dest}${relativePath}`); + await fs.copy(src, `${dest}${relativePath}`, { overwrite: true }); }), ); } diff --git a/development/build/styles.js b/development/build/styles.js index 8b5ccf29e..d6be078ab 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -66,12 +66,10 @@ function createStyleTasks({ livereload }) { async function buildScssPipeline(src, dest, devMode, rtl) { if (!sass) { - // eslint-disable-next-line node/global-require - sass = require('gulp-dart-sass'); // use our own compiler which runs sass in its own process // in order to not pollute the intrinsics // eslint-disable-next-line node/global-require - sass.compiler = require('./sass-compiler'); + sass = require('gulp-sass')(require('./sass-compiler')); } await pump( ...[ diff --git a/development/build/task.js b/development/build/task.js index 328f65e64..1b28a15f6 100644 --- a/development/build/task.js +++ b/development/build/task.js @@ -80,12 +80,9 @@ function runInChildProcess( ); // forward logs to main process - // skip the first stdout event (announcing the process command) - childProcess.stdout.once('data', () => { - childProcess.stdout.on('data', (data) => - process.stdout.write(`${taskName}: ${data}`), - ); - }); + childProcess.stdout.on('data', (data) => + process.stdout.write(`${taskName}: ${data}`), + ); childProcess.stderr.on('data', (data) => process.stderr.write(`${taskName}: ${data}`), diff --git a/development/build/transforms/README.md b/development/build/transforms/README.md index de1e8d0c5..6d8655e22 100644 --- a/development/build/transforms/README.md +++ b/development/build/transforms/README.md @@ -29,7 +29,7 @@ this.store.updateStructure({ ..., GasFeeController: this.gasFeeController, TokenListController: this.tokenListController, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(build-flask) SnapController: this.snapController, ///: END:ONLY_INCLUDE_IN }); @@ -49,7 +49,7 @@ Note that multiple build types can be specified by separating them with commands inside the parameter parentheses: ```javascript -///: BEGIN:ONLY_INCLUDE_IN(beta,flask) +///: BEGIN:ONLY_INCLUDE_IN(build-beta,build-flask) ``` ### Gotchas @@ -114,7 +114,7 @@ only be included in a particular build type, say `beta`, they should be wrapped as follows: ```javascript -///: BEGIN:ONLY_INCLUDE_IN(beta) +///: BEGIN:ONLY_INCLUDE_IN(build-beta) console.log('I am only included in beta builds.'); ///: END:ONLY_INCLUDE_IN ``` diff --git a/development/build/transforms/remove-fenced-code.d.ts b/development/build/transforms/remove-fenced-code.d.ts new file mode 100644 index 000000000..81d249c52 --- /dev/null +++ b/development/build/transforms/remove-fenced-code.d.ts @@ -0,0 +1,4 @@ +export type Features = { + active: ReadonlySet; + all: ReadonlySet; +}; diff --git a/development/build/transforms/remove-fenced-code.js b/development/build/transforms/remove-fenced-code.js index 367173329..3f2a7b5cd 100644 --- a/development/build/transforms/remove-fenced-code.js +++ b/development/build/transforms/remove-fenced-code.js @@ -1,6 +1,5 @@ const path = require('path'); const { PassThrough, Transform } = require('stream'); -const { BuildType, BuildTypeInheritance } = require('../../lib/build-type'); const { lintTransformedFile } = require('./utils'); const hasKey = (obj, key) => Reflect.hasOwnProperty.call(obj, key); @@ -18,14 +17,14 @@ class RemoveFencedCodeTransform extends Transform { * Optionally lints the file if it was modified. * * @param {string} filePath - The path to the file being transformed. - * @param {string} buildType - The type of the current build process. + * @param {import('./remove-fenced-code').Features} features - Features that are currently enabled. * @param {boolean} shouldLintTransformedFiles - Whether the file should be * linted if modified by the transform. */ - constructor(filePath, buildType, shouldLintTransformedFiles) { + constructor(filePath, features, shouldLintTransformedFiles) { super(); this.filePath = filePath; - this.buildType = buildType; + this.features = features; this.shouldLintTransformedFiles = shouldLintTransformedFiles; this._fileBuffers = []; } @@ -45,7 +44,7 @@ class RemoveFencedCodeTransform extends Transform { try { [fileContent, didModify] = removeFencedCode( this.filePath, - this.buildType, + this.features, Buffer.concat(this._fileBuffers).toString('utf8'), ); } catch (error) { @@ -82,20 +81,14 @@ class RemoveFencedCodeTransform extends Transform { * file is ignored by ESLint, since linting is our first line of defense against * making un-syntactic modifications to files using code fences. * - * @param {string} buildType - The type of the current build. + * @param {import('./remove-fenced-code').Features} features - Features that are currently enabled. * @param {boolean} shouldLintTransformedFiles - Whether to lint transformed files. * @returns {(filePath: string) => Transform} The transform function. */ function createRemoveFencedCodeTransform( - buildType, + features, shouldLintTransformedFiles = true, ) { - if (!hasKey(BuildType, buildType)) { - throw new Error( - `Code fencing transform received unrecognized build type "${buildType}".`, - ); - } - // Browserify transforms are functions that receive a file name and return a // duplex stream. The stream receives the file contents piecemeal in the form // of Buffers. @@ -117,7 +110,7 @@ function createRemoveFencedCodeTransform( return new RemoveFencedCodeTransform( filePath, - buildType, + features, shouldLintTransformedFiles, ); }; @@ -132,31 +125,39 @@ const DirectiveCommands = { ONLY_INCLUDE_IN: 'ONLY_INCLUDE_IN', }; -const CommandValidators = { - [DirectiveCommands.ONLY_INCLUDE_IN]: (params, filePath) => { - if (!params || params.length === 0) { - throw new Error( - getInvalidParamsMessage( - filePath, - DirectiveCommands.ONLY_INCLUDE_IN, - `No params specified.`, - ), - ); - } - - params.forEach((param) => { - if (!hasKey(BuildType, param)) { +/** + * Factory function for command validators. + * + * @param {{ features: import('./remove-fenced-code').Features }} config - Configuration required for validation. + * @returns A mapping of command -> validator function. + */ +function CommandValidators({ features }) { + return { + [DirectiveCommands.ONLY_INCLUDE_IN]: (params, filePath) => { + if (!params || params.length === 0) { throw new Error( getInvalidParamsMessage( filePath, DirectiveCommands.ONLY_INCLUDE_IN, - `"${param}" is not a valid build type.`, + `No params specified.`, ), ); } - }); - }, -}; + + for (const param of params) { + if (!features.all.has(param)) { + throw new Error( + getInvalidParamsMessage( + filePath, + DirectiveCommands.ONLY_INCLUDE_IN, + `"${param}" is not a declared build feature.`, + ), + ); + } + } + }, + }; +} // Matches lines starting with "///:", and any preceding whitespace, except // newlines. We except newlines to avoid eating blank lines preceding a fenced @@ -171,7 +172,8 @@ const fenceSentinelRegex = /^\s*\/\/\/:/u; // At this stage of parsing, we are looking for one of: // - TERMINUS:COMMAND(PARAMS) // - TERMINUS:COMMAND -const directiveParsingRegex = /^([A-Z]+):([A-Z_]+)(?:\(((?:\w+,)*\w+)\))?$/u; +const directiveParsingRegex = + /^([A-Z]+):([A-Z_]+)(?:\(((?:\w[-\w]*,)*\w[-\w]*)\))?$/u; /** * Removes fenced code from the given JavaScript source string. "Fenced code" @@ -186,7 +188,7 @@ const directiveParsingRegex = /^([A-Z]+):([A-Z_]+)(?:\(((?:\w+,)*\w+)\))?$/u; * Here's an example of a valid fence: * * ```javascript - * ///: BEGIN:ONLY_INCLUDE_IN(flask) + * ///: BEGIN:ONLY_INCLUDE_IN(build-flask) * console.log('I am Flask.'); * ///: END:ONLY_INCLUDE_IN * ``` @@ -194,12 +196,12 @@ const directiveParsingRegex = /^([A-Z]+):([A-Z_]+)(?:\(((?:\w+,)*\w+)\))?$/u; * For details, please see the documentation. * * @param {string} filePath - The path to the file being transformed. - * @param {string} typeOfCurrentBuild - The type of the current build. + * @param {import('./remove-fenced-code').Features} features - Features that are currently active. * @param {string} fileContent - The contents of the file being transformed. * @returns {[string, modified]} A tuple of the post-transform file contents and * a boolean indicating whether they were modified. */ -function removeFencedCode(filePath, typeOfCurrentBuild, fileContent) { +function removeFencedCode(filePath, features, fileContent) { // Do not modify the file if we detect an inline sourcemap. For reasons // yet to be determined, the transform receives every file twice while in // watch mode, the second after Babel has transpiled the file. Babel adds @@ -318,6 +320,7 @@ function removeFencedCode(filePath, typeOfCurrentBuild, fileContent) { const splicingIndices = []; let shouldSplice = false; let currentCommand; + const commandValidators = CommandValidators({ features }); for (let i = 0; i < parsedDirectives.length; i++) { const { line, indices, terminus, command, parameters } = @@ -335,21 +338,17 @@ function removeFencedCode(filePath, typeOfCurrentBuild, fileContent) { currentCommand = command; // Throws an error if the command parameters are invalid - CommandValidators[command](parameters, filePath); + commandValidators[command](parameters, filePath); - const validBuildTypes = [ - typeOfCurrentBuild, - ...(BuildTypeInheritance[typeOfCurrentBuild] || []), - ]; - - const buildTypeMatches = validBuildTypes.some((validBuildType) => - parameters.includes(validBuildType), + const blockIsActive = parameters.some((param) => + features.active.has(param), ); - if (buildTypeMatches) { + if (blockIsActive) { shouldSplice = false; } else { shouldSplice = true; + // Add start index of BEGIN directive line to splicing indices splicingIndices.push(indices[0]); } diff --git a/development/build/transforms/remove-fenced-code.test.js b/development/build/transforms/remove-fenced-code.test.js index c38550cd4..ac39cc394 100644 --- a/development/build/transforms/remove-fenced-code.test.js +++ b/development/build/transforms/remove-fenced-code.test.js @@ -1,5 +1,5 @@ const deepFreeze = require('deep-freeze-strict'); -const { BuildType } = require('../../lib/build-type'); +const { loadBuildTypesConfig } = require('../../lib/build-type'); const { createRemoveFencedCodeTransform, removeFencedCode, @@ -14,12 +14,22 @@ jest.mock('./utils', () => ({ // file because it takes up a lot of lines and is very distracting. const testData = getTestData(); -const getMinimalFencedCode = (params = 'flask') => +const MAIN_BUILD = 'build-main'; +const FLASK_BUILD = 'build-flask'; + +const getMinimalFencedCode = (params = FLASK_BUILD) => `///: BEGIN:ONLY_INCLUDE_IN(${params}) Conditionally_Included ///: END:ONLY_INCLUDE_IN `; +const getFeatures = ({ all, active }) => ({ + all: new Set(all), + active: new Set(active), +}); + +const buildTypesConfig = loadBuildTypesConfig(); + describe('build/transforms/remove-fenced-code', () => { describe('createRemoveFencedCodeTransform', () => { const { lintTransformedFile: lintTransformedFileMock } = transformUtils; @@ -29,15 +39,14 @@ describe('build/transforms/remove-fenced-code', () => { lintTransformedFileMock.mockImplementation(() => Promise.resolve()); }); - it('rejects invalid build types', () => { - expect(() => createRemoveFencedCodeTransform('foobar')).toThrow( - /received unrecognized build type "foobar".$/u, - ); - }); - it('returns a PassThrough stream for files with ignored extensions', async () => { const fileContent = '"Valid JSON content"\n'; - const stream = createRemoveFencedCodeTransform('main')('file.json'); + const stream = createRemoveFencedCodeTransform( + getFeatures({ + active: [MAIN_BUILD], + all: [MAIN_BUILD], + }), + )('file.json'); let streamOutput = ''; await new Promise((resolve) => { @@ -60,7 +69,12 @@ describe('build/transforms/remove-fenced-code', () => { const filePrefix = '// A comment\n'; const fileContent = filePrefix.concat(getMinimalFencedCode()); - const stream = createRemoveFencedCodeTransform('main')(mockJsFileName); + const stream = createRemoveFencedCodeTransform( + getFeatures({ + active: [MAIN_BUILD], + all: [MAIN_BUILD, FLASK_BUILD], + }), + )(mockJsFileName); let streamOutput = ''; await new Promise((resolve) => { @@ -92,7 +106,12 @@ describe('build/transforms/remove-fenced-code', () => { .filter((line) => line !== '') .map((line) => `${line}\n`); - const stream = createRemoveFencedCodeTransform('main')(mockJsFileName); + const stream = createRemoveFencedCodeTransform( + getFeatures({ + active: [MAIN_BUILD], + all: [MAIN_BUILD, FLASK_BUILD], + }), + )(mockJsFileName); let streamOutput = ''; await new Promise((resolve) => { @@ -116,9 +135,14 @@ describe('build/transforms/remove-fenced-code', () => { }); it('handles file with fences that is unmodified by the transform', async () => { - const fileContent = getMinimalFencedCode('main'); + const fileContent = getMinimalFencedCode(MAIN_BUILD); - const stream = createRemoveFencedCodeTransform('main')(mockJsFileName); + const stream = createRemoveFencedCodeTransform( + getFeatures({ + active: [MAIN_BUILD], + all: [MAIN_BUILD], + }), + )(mockJsFileName); let streamOutput = ''; await new Promise((resolve) => { @@ -141,7 +165,7 @@ describe('build/transforms/remove-fenced-code', () => { const fileContent = filePrefix.concat(getMinimalFencedCode()); const stream = createRemoveFencedCodeTransform( - 'main', + getFeatures({ all: [MAIN_BUILD, FLASK_BUILD], active: [MAIN_BUILD] }), false, )(mockJsFileName); let streamOutput = ''; @@ -166,7 +190,9 @@ describe('build/transforms/remove-fenced-code', () => { '///: END:ONLY_INCLUDE_IN', ); - const stream = createRemoveFencedCodeTransform('main')(mockJsFileName); + const stream = createRemoveFencedCodeTransform( + getFeatures({ all: [MAIN_BUILD, FLASK_BUILD], active: [MAIN_BUILD] }), + )(mockJsFileName); await new Promise((resolve) => { stream.on('error', (error) => { @@ -191,7 +217,9 @@ describe('build/transforms/remove-fenced-code', () => { const filePrefix = '// A comment\n'; const fileContent = filePrefix.concat(getMinimalFencedCode()); - const stream = createRemoveFencedCodeTransform('main')(mockJsFileName); + const stream = createRemoveFencedCodeTransform( + getFeatures({ all: [FLASK_BUILD], active: [] }), + )(mockJsFileName); await new Promise((resolve) => { stream.on('error', (error) => { @@ -213,12 +241,15 @@ describe('build/transforms/remove-fenced-code', () => { const mockFileName = 'file.js'; // Valid inputs - Object.keys(BuildType).forEach((buildType) => { + ['main', 'flask', 'beta'].forEach((buildType) => { + const active = buildTypesConfig.buildTypes[buildType].features; + const all = Object.keys(buildTypesConfig.features); + const features = getFeatures({ all, active }); it(`transforms file with fences for build type "${buildType}"`, () => { expect( removeFencedCode( mockFileName, - buildType, + features, testData.validInputs.withFences, ), ).toStrictEqual(testData.validOutputs[buildType]); @@ -226,15 +257,15 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - buildType, + features, testData.validInputs.extraContentWithFences, ), ).toStrictEqual(testData.validOutputsWithExtraContent[buildType]); // Ensure that the minimal input template is in fact valid - const minimalInput = getMinimalFencedCode(buildType); + const minimalInput = getMinimalFencedCode(`build-${buildType}`); expect( - removeFencedCode(mockFileName, buildType, minimalInput), + removeFencedCode(mockFileName, features, minimalInput), ).toStrictEqual([minimalInput, false]); }); @@ -242,7 +273,7 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - buildType, + features, testData.validInputs.withoutFences, ), ).toStrictEqual([testData.validInputs.withoutFences, false]); @@ -250,7 +281,7 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - buildType, + features, testData.validInputs.extraContentWithoutFences, ), ).toStrictEqual([ @@ -265,29 +296,17 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - BuildType.flask, - getMinimalFencedCode('main'), + getFeatures({ + active: [FLASK_BUILD], + all: [FLASK_BUILD, MAIN_BUILD], + }), + getMinimalFencedCode(MAIN_BUILD), ), ).toStrictEqual(['', true]); }); - it('keeps fences with inherited build types', () => { - // Desktop inherits from the flask build type - const minimalCode = - getMinimalFencedCode(BuildType.flask) + - getMinimalFencedCode(BuildType.desktop); - - expect( - removeFencedCode(mockFileName, BuildType.desktop, minimalCode), - ).toStrictEqual([minimalCode, false]); - - expect( - removeFencedCode(mockFileName, BuildType.flask, minimalCode), - ).toStrictEqual([getMinimalFencedCode(BuildType.flask), true]); - }); - it('ignores sentinels preceded by non-whitespace', () => { - const validBeginDirective = '///: BEGIN:ONLY_INCLUDE_IN(flask)\n'; + const validBeginDirective = '///: BEGIN:ONLY_INCLUDE_IN(build-flask)\n'; const ignoredLines = [ `a ${validBeginDirective}`, `2 ${validBeginDirective}`, @@ -299,8 +318,11 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - BuildType.flask, - getMinimalFencedCode('main').concat(ignoredLine), + getFeatures({ + active: [FLASK_BUILD], + all: [FLASK_BUILD, MAIN_BUILD], + }), + getMinimalFencedCode(MAIN_BUILD).concat(ignoredLine), ), ).toStrictEqual([ignoredLine, true]); @@ -311,7 +333,7 @@ describe('build/transforms/remove-fenced-code', () => { expect( removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), modifiedInputWithoutFences, ), ).toStrictEqual([modifiedInputWithoutFences, false]); @@ -341,7 +363,11 @@ describe('build/transforms/remove-fenced-code', () => { inputs.forEach((input) => { expect(() => - removeFencedCode(mockFileName, BuildType.flask, input), + removeFencedCode( + mockFileName, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), + input, + ), ).toThrow( `Empty fence found in file "${mockFileName}":\n${emptyFence}`, ); @@ -368,7 +394,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().replace( fenceSentinelAndTerminusRegex, replacement, @@ -382,53 +408,53 @@ describe('build/transforms/remove-fenced-code', () => { it('rejects malformed BEGIN directives', () => { // This is the first line of the minimal input template - const directiveString = '///: BEGIN:ONLY_INCLUDE_IN(flask)'; + const directiveString = '///: BEGIN:ONLY_INCLUDE_IN(build-flask)'; const replacements = [ // Invalid terminus - '///: BE_GIN:ONLY_INCLUDE_IN(flask)', - '///: BE6IN:ONLY_INCLUDE_IN(flask)', - '///: BEGIN7:ONLY_INCLUDE_IN(flask)', - '///: BeGIN:ONLY_INCLUDE_IN(flask)', - '///: BE3:ONLY_INCLUDE_IN(flask)', - '///: BEG-IN:ONLY_INCLUDE_IN(flask)', - '///: BEG N:ONLY_INCLUDE_IN(flask)', + '///: BE_GIN:BEGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BE6IN:BEGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BEGIN7:BEGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BeGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BE3:BEGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BEG-IN:BEGIN:ONLY_INCLUDE_IN(build-flask)', + '///: BEG N:BEGIN:ONLY_INCLUDE_IN(build-flask)', // Invalid commands '///: BEGIN:ONLY-INCLUDE_IN(flask)', '///: BEGIN:ONLY_INCLUDE:IN(flask)', '///: BEGIN:ONL6_INCLUDE_IN(flask)', '///: BEGIN:ONLY_IN@LUDE_IN(flask)', - '///: BEGIN:ONLy_INCLUDE_IN(flask)', + '///: BEGIN:ONLy_INCLUDE_IN(build-flask)', '///: BEGIN:ONLY INCLUDE_IN(flask)', // Invalid parameters '///: BEGIN:ONLY_INCLUDE_IN(,flask)', - '///: BEGIN:ONLY_INCLUDE_IN(flask,)', - '///: BEGIN:ONLY_INCLUDE_IN(flask,,main)', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask,)', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask,,main)', '///: BEGIN:ONLY_INCLUDE_IN(,)', '///: BEGIN:ONLY_INCLUDE_IN()', '///: BEGIN:ONLY_INCLUDE_IN( )', - '///: BEGIN:ONLY_INCLUDE_IN(flask]', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask]', '///: BEGIN:ONLY_INCLUDE_IN[flask)', - '///: BEGIN:ONLY_INCLUDE_IN(flask.main)', - '///: BEGIN:ONLY_INCLUDE_IN(flask,@)', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask.main)', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask,@)', '///: BEGIN:ONLY_INCLUDE_IN(fla k)', // Stuff after the directive - '///: BEGIN:ONLY_INCLUDE_IN(flask) A', - '///: BEGIN:ONLY_INCLUDE_IN(flask) 9', - '///: BEGIN:ONLY_INCLUDE_IN(flask)A', - '///: BEGIN:ONLY_INCLUDE_IN(flask)9', - '///: BEGIN:ONLY_INCLUDE_IN(flask)_', - '///: BEGIN:ONLY_INCLUDE_IN(flask))', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask) A', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask) 9', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask)A', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask)9', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask)_', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask))', ]; replacements.forEach((replacement) => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().replace(directiveString, replacement), ), ).toThrow( @@ -474,7 +500,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().replace(directiveString, replacement), ), ).toThrow( @@ -488,14 +514,14 @@ describe('build/transforms/remove-fenced-code', () => { it('rejects files with uneven number of fence lines', () => { const additions = [ - '///: BEGIN:ONLY_INCLUDE_IN(flask)', + '///: BEGIN:ONLY_INCLUDE_IN(build-flask)', '///: END:ONLY_INCLUDE_IN', ]; additions.forEach((addition) => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().concat(addition), ), ).toThrow( @@ -515,7 +541,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().replace(validTerminus, replacement), ), ).toThrow( @@ -539,7 +565,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode().replace(validCommand, replacement), ), ).toThrow( @@ -557,10 +583,30 @@ describe('build/transforms/remove-fenced-code', () => { it('rejects invalid command parameters', () => { const testCases = [ - ['bar', ['bar', 'flask,bar', 'flask,beta,main,bar']], - ['Foo', ['Foo', 'flask,Foo', 'flask,beta,main,Foo']], - ['b3ta', ['b3ta', 'flask,b3ta', 'flask,beta,main,b3ta']], - ['bEta', ['bEta', 'flask,bEta', 'flask,beta,main,bEta']], + [ + 'bar', + ['bar', 'build-flask,bar', 'build-flask,build-beta,build-main,bar'], + ], + [ + 'Foo', + ['Foo', 'build-flask,Foo', 'build-flask,build-beta,build-main,Foo'], + ], + [ + 'b3ta', + [ + 'b3ta', + 'build-flask,b3ta', + 'build-flask,build-beta,build-main,b3ta', + ], + ], + [ + 'bEta', + [ + 'bEta', + 'build-flask,bEta', + 'build-flask,build-beta,build-main,bEta', + ], + ], ]; testCases.forEach(([invalidParam, replacements]) => { @@ -568,11 +614,17 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ + active: [FLASK_BUILD], + all: [FLASK_BUILD, MAIN_BUILD, 'build-beta'], + }), getMinimalFencedCode(replacement), ), ).toThrow( - new RegExp(`"${invalidParam}" is not a valid build type.$`, 'u'), + new RegExp( + `"${invalidParam}" is not a declared build feature.$`, + 'u', + ), ); }); }); @@ -581,7 +633,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), getMinimalFencedCode('').replace('()', ''), ), ).toThrow(/No params specified.$/u); @@ -589,7 +641,9 @@ describe('build/transforms/remove-fenced-code', () => { it('rejects directive pairs with wrong terminus order', () => { // We need more than one directive pair for this test - const input = getMinimalFencedCode().concat(getMinimalFencedCode('beta')); + const input = getMinimalFencedCode().concat( + getMinimalFencedCode('build-beta'), + ); const expectedBeginError = 'The first directive of a pair must be a "BEGIN" directive.'; @@ -597,17 +651,17 @@ describe('build/transforms/remove-fenced-code', () => { 'The second directive of a pair must be an "END" directive.'; const testCases = [ [ - 'BEGIN:ONLY_INCLUDE_IN(flask)', + 'BEGIN:ONLY_INCLUDE_IN(build-flask)', 'END:ONLY_INCLUDE_IN', expectedBeginError, ], [ /END:ONLY_INCLUDE_IN/mu, - 'BEGIN:ONLY_INCLUDE_IN(main)', + 'BEGIN:ONLY_INCLUDE_IN(build-main)', expectedEndError, ], [ - 'BEGIN:ONLY_INCLUDE_IN(beta)', + 'BEGIN:ONLY_INCLUDE_IN(build-beta)', 'END:ONLY_INCLUDE_IN', expectedBeginError, ], @@ -617,7 +671,7 @@ describe('build/transforms/remove-fenced-code', () => { expect(() => removeFencedCode( mockFileName, - BuildType.flask, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), input.replace(target, replacement), ), ).toThrow(expectedError); @@ -631,7 +685,11 @@ describe('build/transforms/remove-fenced-code', () => { '\n//# sourceMappingURL=as32e32wcwc2234f2ew32cnin4243f4nv9nsdoivnxzoivnd', ); expect( - removeFencedCode(mockFileName, BuildType.flask, input), + removeFencedCode( + mockFileName, + getFeatures({ active: [FLASK_BUILD], all: [FLASK_BUILD] }), + input, + ), ).toStrictEqual([input, false]); }); @@ -644,14 +702,14 @@ function getTestData() { const data = { validInputs: { withFences: ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -660,7 +718,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -678,7 +736,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -690,14 +748,14 @@ Conditionally_Included `, extraContentWithFences: ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -706,7 +764,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -723,7 +781,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -781,14 +839,14 @@ Always_Included validOutputs: { beta: [ ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -810,14 +868,14 @@ Always_Included ], flask: [ ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -826,7 +884,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -836,16 +894,25 @@ Always_Included Always_Included Always_Included Always_Included +///: BEGIN:ONLY_INCLUDE_IN(desktop) + +Conditionally_Included +Conditionally_Included +///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included +///: END:ONLY_INCLUDE_IN +///: BEGIN:ONLY_INCLUDE_IN(desktop) +Conditionally_Included +Conditionally_Included ///: END:ONLY_INCLUDE_IN `, - true, + false, ], mmi: [ ` @@ -872,14 +939,14 @@ Always_Included validOutputsWithExtraContent: { beta: [ ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -904,14 +971,14 @@ Always_Included ], flask: [ ` -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included ///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask,beta,desktop) +///: BEGIN:ONLY_INCLUDE_IN(build-flask,build-beta,desktop) Conditionally_Included Conditionally_Included @@ -920,7 +987,7 @@ Conditionally_Included Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) Conditionally_Included Conditionally_Included @@ -930,10 +997,19 @@ Always_Included Always_Included Always_Included Always_Included +///: BEGIN:ONLY_INCLUDE_IN(desktop) +Conditionally_Included +Conditionally_Included +///: END:ONLY_INCLUDE_IN Always_Included Always_Included Always_Included -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(build-flask) +Conditionally_Included +Conditionally_Included + +///: END:ONLY_INCLUDE_IN +///: BEGIN:ONLY_INCLUDE_IN(desktop) Conditionally_Included Conditionally_Included @@ -942,7 +1018,7 @@ Always_Included Always_Included Always_Included `, - true, + false, ], mmi: [ ` diff --git a/development/build/utils.js b/development/build/utils.js index ce88d1f09..9b5bd58e3 100644 --- a/development/build/utils.js +++ b/development/build/utils.js @@ -1,6 +1,6 @@ const path = require('path'); const semver = require('semver'); -const { BuildType } = require('../lib/build-type'); +const { loadBuildTypesConfig } = require('../lib/build-type'); const { BUILD_TARGETS, ENVIRONMENT } = require('./constants'); /** @@ -48,6 +48,8 @@ function getBrowserVersionMap(platforms, version) { let buildType, buildVersionSummary, buildVersion; if (prerelease) { [buildType, buildVersionSummary] = prerelease; + // TODO(ritave): Figure out why the version 10.25.0-beta.1-flask.0 in the below comment is even possible + // since those are two different build types // The version could be version: '10.25.0-beta.1-flask.0', // That results in buildVersionSummary becomes 1-flask // And we only want 1 from this string @@ -57,14 +59,7 @@ function getBrowserVersionMap(platforms, version) { : buildVersionSummary; if (!String(buildVersion).match(/^\d+$/u)) { throw new Error(`Invalid prerelease build version: '${buildVersion}'`); - } else if ( - ![ - BuildType.beta, - BuildType.flask, - BuildType.desktop, - BuildType.mmi, - ].includes(buildType) - ) { + } else if (!loadBuildTypesConfig().buildTypes[buildType].isPrerelease) { throw new Error(`Invalid prerelease build type: ${buildType}`); } } diff --git a/development/fitness-functions/check-mocha-syntax.js b/development/fitness-functions/check-mocha-syntax.js deleted file mode 100644 index 2e4cea384..000000000 --- a/development/fitness-functions/check-mocha-syntax.js +++ /dev/null @@ -1,44 +0,0 @@ -const { - EXCLUDE_E2E_TESTS_REGEX, - filterDiffAdditions, - filterDiffByFilePath, - hasNumberOfCodeBlocksIncreased, -} = require('./shared'); - -function checkMochaSyntax(diff) { - const ruleHeading = 'favor-jest-instead-of-mocha'; - const codeBlocks = [ - "import { strict as assert } from 'assert';", - 'assert.deepEqual', - 'assert.equal', - 'assert.rejects', - 'assert.strictEqual', - 'sinon.', - ]; - - console.log(`\nChecking ${ruleHeading}...`); - - const diffByFilePath = filterDiffByFilePath(diff, EXCLUDE_E2E_TESTS_REGEX); - const diffAdditions = filterDiffAdditions(diffByFilePath); - const hashmap = hasNumberOfCodeBlocksIncreased(diffAdditions, codeBlocks); - - Object.keys(hashmap).forEach((key) => { - if (hashmap[key]) { - console.error(`Number of occurences of "${key}" have increased.`); - } - }); - - if (Object.values(hashmap).includes(true)) { - console.error( - `...changes have not been accepted by the fitness function.\nFor more info, see: https://github.com/MetaMask/metamask-extension/blob/develop/docs/testing.md#${ruleHeading}`, - ); - process.exit(1); - } else { - console.log( - `...number of occurences has not increased for any code block.`, - ); - process.exit(0); - } -} - -module.exports = { checkMochaSyntax }; diff --git a/development/fitness-functions/common/constants.test.ts b/development/fitness-functions/common/constants.test.ts new file mode 100644 index 000000000..21912d5fa --- /dev/null +++ b/development/fitness-functions/common/constants.test.ts @@ -0,0 +1,105 @@ +import { EXCLUDE_E2E_TESTS_REGEX, SHARED_FOLDER_JS_REGEX } from './constants'; + +describe('Regular Expressions used in Fitness Functions', (): void => { + describe(`EXCLUDE_E2E_TESTS_REGEX "${EXCLUDE_E2E_TESTS_REGEX}"`, (): void => { + const PATHS_IT_SHOULD_MATCH = [ + 'file.js', + 'path/file.js', + 'much/longer/path/file.js', + 'file.ts', + 'path/file.ts', + 'much/longer/path/file.ts', + 'file.jsx', + 'path/file.jsx', + 'much/longer/path/file.jsx', + ]; + + const PATHS_IT_SHOULD_NOT_MATCH = [ + // any without JS, TS, JSX or TSX extension + 'file', + 'file.extension', + 'path/file.extension', + 'much/longer/path/file.extension', + // any in the test/e2e directory + 'test/e2e/file', + 'test/e2e/file.extension', + 'test/e2e/path/file.extension', + 'test/e2e/much/longer/path/file.extension', + 'test/e2e/file.js', + 'test/e2e/path/file.ts', + 'test/e2e/much/longer/path/file.jsx', + 'test/e2e/much/longer/path/file.tsx', + // any in the development/fitness-functions directory + 'development/fitness-functions/file', + 'development/fitness-functions/file.extension', + 'development/fitness-functions/path/file.extension', + 'development/fitness-functions/much/longer/path/file.extension', + 'development/fitness-functions/file.js', + 'development/fitness-functions/path/file.ts', + 'development/fitness-functions/much/longer/path/file.jsx', + 'development/fitness-functions/much/longer/path/file.tsx', + ]; + + describe('included paths', (): void => { + PATHS_IT_SHOULD_MATCH.forEach((path: string): void => { + it(`should match "${path}"`, (): void => { + const result = new RegExp(EXCLUDE_E2E_TESTS_REGEX, 'u').test(path); + + expect(result).toStrictEqual(true); + }); + }); + }); + + describe('excluded paths', (): void => { + PATHS_IT_SHOULD_NOT_MATCH.forEach((path: string): void => { + it(`should not match "${path}"`, (): void => { + const result = new RegExp(EXCLUDE_E2E_TESTS_REGEX, 'u').test(path); + + expect(result).toStrictEqual(false); + }); + }); + }); + }); + + describe(`SHARED_FOLDER_JS_REGEX "${SHARED_FOLDER_JS_REGEX}"`, (): void => { + const PATHS_IT_SHOULD_MATCH = [ + 'shared/file.js', + 'shared/path/file.js', + 'shared/much/longer/path/file.js', + 'shared/file.jsx', + 'shared/path/file.jsx', + 'shared/much/longer/path/file.jsx', + ]; + + const PATHS_IT_SHOULD_NOT_MATCH = [ + // any without JS or JSX extension + 'file', + 'file.extension', + 'path/file.extension', + 'much/longer/path/file.extension', + 'file.ts', + 'path/file.ts', + 'much/longer/path/file.tsx', + ]; + + describe('included paths', (): void => { + PATHS_IT_SHOULD_MATCH.forEach((path: string): void => { + it(`should match "${path}"`, (): void => { + const result = new RegExp(SHARED_FOLDER_JS_REGEX, 'u').test(path); + + expect(result).toStrictEqual(true); + }); + }); + }); + + describe('excluded paths', (): void => { + PATHS_IT_SHOULD_NOT_MATCH.forEach((path: string): void => { + it(`should not match "${path}"`, (): void => { + const result = new RegExp(SHARED_FOLDER_JS_REGEX, 'u').test(path); + + expect(result).toStrictEqual(false); + }); + }); + }); + }); +}); diff --git a/development/fitness-functions/common/constants.ts b/development/fitness-functions/common/constants.ts new file mode 100644 index 000000000..0514c6ed9 --- /dev/null +++ b/development/fitness-functions/common/constants.ts @@ -0,0 +1,15 @@ +// include JS, TS, JSX, TSX files only excluding files in the e2e tests and +// fitness functions directories +const EXCLUDE_E2E_TESTS_REGEX = + '^(?!test/e2e)(?!development/fitness).*.(js|ts|jsx|tsx)$'; + +// include JS and JSX files in the shared directory only +const SHARED_FOLDER_JS_REGEX = '^(shared).*.(js|jsx)$'; + +enum AUTOMATION_TYPE { + CI = 'ci', + PRE_COMMIT_HOOK = 'pre-commit-hook', + PRE_PUSH_HOOK = 'pre-push-hook', +} + +export { EXCLUDE_E2E_TESTS_REGEX, SHARED_FOLDER_JS_REGEX, AUTOMATION_TYPE }; diff --git a/development/fitness-functions/common/get-diff.ts b/development/fitness-functions/common/get-diff.ts new file mode 100644 index 000000000..620d53b63 --- /dev/null +++ b/development/fitness-functions/common/get-diff.ts @@ -0,0 +1,54 @@ +import { execSync } from 'child_process'; +import fs from 'fs'; +import { AUTOMATION_TYPE } from './constants'; + +function getDiffByAutomationType( + automationType: AUTOMATION_TYPE, +): string | undefined { + if (!Object.values(AUTOMATION_TYPE).includes(automationType)) { + console.error('Invalid automation type.'); + process.exit(1); + } + + let diff; + if (automationType === AUTOMATION_TYPE.CI) { + const optionalArguments = process.argv.slice(3); + if (optionalArguments.length !== 1) { + console.error('Invalid number of arguments.'); + process.exit(1); + } + + diff = getCIDiff(optionalArguments[0]); + } else if (automationType === AUTOMATION_TYPE.PRE_COMMIT_HOOK) { + diff = getPreCommitHookDiff(); + } else if (automationType === AUTOMATION_TYPE.PRE_PUSH_HOOK) { + diff = getPrePushHookDiff(); + } + + return diff; +} + +function getCIDiff(path: string): string { + return fs.readFileSync(path, { + encoding: 'utf8', + flag: 'r', + }); +} + +function getPreCommitHookDiff(): string { + return execSync(`git diff --cached HEAD`).toString().trim(); +} + +function getPrePushHookDiff(): string { + const currentBranch = execSync(`git rev-parse --abbrev-ref HEAD`) + .toString() + .trim(); + + return execSync( + `git diff ${currentBranch} origin/${currentBranch} -- . ':(exclude)development/fitness-functions/'`, + ) + .toString() + .trim(); +} + +export { getDiffByAutomationType }; diff --git a/development/fitness-functions/shared.test.js b/development/fitness-functions/common/shared.test.ts similarity index 59% rename from development/fitness-functions/shared.test.js rename to development/fitness-functions/common/shared.test.ts index 6b464aafd..92306b9d4 100644 --- a/development/fitness-functions/shared.test.js +++ b/development/fitness-functions/common/shared.test.ts @@ -1,46 +1,48 @@ -const { - EXCLUDE_E2E_TESTS_REGEX, - filterDiffAdditions, +import { + filterDiffLineAdditions, hasNumberOfCodeBlocksIncreased, filterDiffByFilePath, -} = require('./shared'); + filterDiffFileCreations, +} from './shared'; +import { generateCreateFileDiff, generateModifyFilesDiff } from './test-data'; -const generateCreateFileDiff = (filePath, content) => ` -diff --git a/${filePath} b/${filePath} -new file mode 100644 -index 000000000..30d74d258 ---- /dev/null -+++ b/${filePath} -@@ -0,0 +1 @@ -+${content} -`; - -const generateModifyFilesDiff = (filePath, addition, removal) => ` -diff --git a/${filePath} b/${filePath} -index 57d5de75c..808d8ba37 100644 ---- a/${filePath} -+++ b/${filePath} -@@ -1,3 +1,8 @@ -+${addition} -@@ -34,33 +39,4 @@ --${removal} -`; - -describe('filterDiffAdditions()', () => { - it('should return code additions in the diff', () => { +describe('filterDiffLineAdditions()', (): void => { + it('should return code additions in the diff', (): void => { const testFilePath = 'new-file.js'; const testAddition = 'foo'; const testFileDiff = generateCreateFileDiff(testFilePath, testAddition); - const actualResult = filterDiffAdditions(testFileDiff); + const actualResult = filterDiffLineAdditions(testFileDiff); const expectedResult = `+${testAddition}`; expect(actualResult).toStrictEqual(expectedResult); }); }); -describe('hasNumberOfCodeBlocksIncreased()', () => { - it('should show which code blocks have increased', () => { +describe('filterDiffFileCreations()', (): void => { + it('should return code additions in the diff', (): void => { + const testFileDiff = [ + generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), + generateCreateFileDiff('old-file.js', 'ping'), + generateModifyFilesDiff('old-file.jsx', 'yin', 'yang'), + ].join(''); + + const actualResult = filterDiffFileCreations(testFileDiff); + + expect(actualResult).toMatchInlineSnapshot(` + "diff --git a/old-file.js b/old-file.js + new file mode 100644 + index 000000000..30d74d258 + --- /dev/null + +++ b/old-file.js + @@ -0,0 +1 @@ + +ping" + `); + }); +}); + +describe('hasNumberOfCodeBlocksIncreased()', (): void => { + it('should show which code blocks have increased', (): void => { const testDiffFragment = ` +foo +bar @@ -57,14 +59,14 @@ describe('hasNumberOfCodeBlocksIncreased()', () => { }); }); -describe('filterDiffByFilePath()', () => { +describe('filterDiffByFilePath()', (): void => { const testFileDiff = [ generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), generateModifyFilesDiff('old-file.js', 'ping', 'pong'), generateModifyFilesDiff('old-file.jsx', 'yin', 'yang'), ].join(''); - it('should return the right diff for a generic matcher', () => { + it('should return the right diff for a generic matcher', (): void => { const actualResult = filterDiffByFilePath( testFileDiff, '.*/.*.(js|ts)$|.*.(js|ts)$', @@ -90,7 +92,7 @@ describe('filterDiffByFilePath()', () => { `); }); - it('should return the right diff for a specific file in any dir matcher', () => { + it('should return the right diff for a specific file in any dir matcher', (): void => { const actualResult = filterDiffByFilePath(testFileDiff, '.*old-file.js$'); expect(actualResult).toMatchInlineSnapshot(` @@ -105,7 +107,7 @@ describe('filterDiffByFilePath()', () => { `); }); - it('should return the right diff for a multiple file extension (OR) matcher', () => { + it('should return the right diff for a multiple file extension (OR) matcher', (): void => { const actualResult = filterDiffByFilePath( testFileDiff, '^(./)*old-file.(js|ts|jsx)$', @@ -131,7 +133,7 @@ describe('filterDiffByFilePath()', () => { `); }); - it('should return the right diff for a file name negation matcher', () => { + it('should return the right diff for a file name negation matcher', (): void => { const actualResult = filterDiffByFilePath( testFileDiff, '^(?!.*old-file.js$).*.[a-zA-Z]+$', @@ -157,51 +159,3 @@ describe('filterDiffByFilePath()', () => { `); }); }); - -describe(`EXCLUDE_E2E_TESTS_REGEX "${EXCLUDE_E2E_TESTS_REGEX}"`, () => { - const PATHS_IT_SHOULD_MATCH = [ - 'file.js', - 'path/file.js', - 'much/longer/path/file.js', - 'file.ts', - 'path/file.ts', - 'much/longer/path/file.ts', - 'file.jsx', - 'path/file.jsx', - 'much/longer/path/file.jsx', - ]; - - const PATHS_IT_SHOULD_NOT_MATCH = [ - 'test/e2e/file', - 'test/e2e/file.extension', - 'test/e2e/path/file.extension', - 'test/e2e/much/longer/path/file.extension', - 'test/e2e/file.js', - 'test/e2e/path/file.ts', - 'test/e2e/much/longer/path/file.jsx', - 'file', - 'file.extension', - 'path/file.extension', - 'much/longer/path/file.extension', - ]; - - describe('included paths', () => { - PATHS_IT_SHOULD_MATCH.forEach((path) => { - it(`should match "${path}"`, () => { - const result = new RegExp(EXCLUDE_E2E_TESTS_REGEX, 'u').test(path); - - expect(result).toStrictEqual(true); - }); - }); - }); - - describe('excluded paths', () => { - PATHS_IT_SHOULD_NOT_MATCH.forEach((path) => { - it(`should not match "${path}"`, () => { - const result = new RegExp(EXCLUDE_E2E_TESTS_REGEX, 'u').test(path); - - expect(result).toStrictEqual(false); - }); - }); - }); -}); diff --git a/development/fitness-functions/shared.js b/development/fitness-functions/common/shared.ts similarity index 60% rename from development/fitness-functions/shared.js rename to development/fitness-functions/common/shared.ts index 791837a6d..e24c8cf01 100644 --- a/development/fitness-functions/shared.js +++ b/development/fitness-functions/common/shared.ts @@ -1,6 +1,4 @@ -const EXCLUDE_E2E_TESTS_REGEX = '^(?!test/e2e/).*.(js|ts|jsx)$'; - -function filterDiffByFilePath(diff, regex) { +function filterDiffByFilePath(diff: string, regex: string): string { // split by `diff --git` and remove the first element which is empty const diffBlocks = diff.split(`diff --git`).slice(1); @@ -34,7 +32,7 @@ function filterDiffByFilePath(diff, regex) { return filteredDiff; } -function filterDiffAdditions(diff) { +function filterDiffLineAdditions(diff: string): string { const diffLines = diff.split('\n'); const diffAdditionLines = diffLines.filter((line) => { @@ -46,10 +44,36 @@ function filterDiffAdditions(diff) { return diffAdditionLines.join('/n'); } -function hasNumberOfCodeBlocksIncreased(diffFragment, codeBlocks) { +function filterDiffFileCreations(diff: string): string { + // split by `diff --git` and remove the first element which is empty + const diffBlocks = diff.split(`diff --git`).slice(1); + + const filteredDiff = diffBlocks + .map((block) => block.trim()) + .filter((block) => { + const isFileCreationLine = + block + // get the second line of the block which has the file mode + .split('\n')[1] + .trim() + .substring(0, 13) === 'new file mode'; + + return isFileCreationLine; + }) + // prepend `git --diff` to each block + .map((block) => `diff --git ${block}`) + .join('\n'); + + return filteredDiff; +} + +function hasNumberOfCodeBlocksIncreased( + diffFragment: string, + codeBlocks: string[], +): { [codeBlock: string]: boolean } { const diffLines = diffFragment.split('\n'); - const codeBlockFound = {}; + const codeBlockFound: { [codeBlock: string]: boolean } = {}; for (const codeBlock of codeBlocks) { codeBlockFound[codeBlock] = false; @@ -65,9 +89,9 @@ function hasNumberOfCodeBlocksIncreased(diffFragment, codeBlocks) { return codeBlockFound; } -module.exports = { - EXCLUDE_E2E_TESTS_REGEX, +export { filterDiffByFilePath, - filterDiffAdditions, + filterDiffLineAdditions, + filterDiffFileCreations, hasNumberOfCodeBlocksIncreased, }; diff --git a/development/fitness-functions/common/test-data.ts b/development/fitness-functions/common/test-data.ts new file mode 100644 index 000000000..7dac4dee1 --- /dev/null +++ b/development/fitness-functions/common/test-data.ts @@ -0,0 +1,40 @@ +const generateCreateFileDiff = ( + filePath = 'file.txt', + content = 'Lorem ipsum', +): string => ` +diff --git a/${filePath} b/${filePath} +new file mode 100644 +index 000000000..30d74d258 +--- /dev/null ++++ b/${filePath} +@@ -0,0 +1 @@ ++${content} +`; + +const generateModifyFilesDiff = ( + filePath = 'file.txt', + addition = 'Lorem ipsum', + removal = '', +): string => { + const additionBlock = addition + ? ` +@@ -1,3 +1,8 @@ ++${addition}`.trim() + : ''; + + const removalBlock = removal + ? ` +@@ -34,33 +39,4 @@ +-${removal}`.trim() + : ''; + + return ` +diff --git a/${filePath} b/${filePath} +index 57d5de75c..808d8ba37 100644 +--- a/${filePath} ++++ b/${filePath} +${additionBlock} +${removalBlock}`; +}; + +export { generateCreateFileDiff, generateModifyFilesDiff }; diff --git a/development/fitness-functions/index.js b/development/fitness-functions/index.js deleted file mode 100644 index 37b61819d..000000000 --- a/development/fitness-functions/index.js +++ /dev/null @@ -1,53 +0,0 @@ -const fs = require('fs'); -const { execSync } = require('child_process'); -const { checkMochaSyntax } = require('./check-mocha-syntax'); - -const AUTOMATION_TYPE = Object.freeze({ - CI: 'ci', - PRE_COMMIT_HOOK: 'pre-commit-hook', - PRE_PUSH_HOOK: 'pre-push-hook', -}); - -const automationType = process.argv[2]; - -if (automationType === AUTOMATION_TYPE.CI) { - const optionalArguments = process.argv.slice(3); - if (optionalArguments.length !== 1) { - console.error('Invalid number of arguments.'); - process.exit(1); - } - - const diff = fs.readFileSync(optionalArguments[0], { - encoding: 'utf8', - flag: 'r', - }); - - checkMochaSyntax(diff); -} else if (automationType === AUTOMATION_TYPE.PRE_COMMIT_HOOK) { - const diff = getPreCommitHookDiff(); - - checkMochaSyntax(diff); -} else if (automationType === AUTOMATION_TYPE.PRE_PUSH_HOOK) { - const diff = getPrePushHookDiff(); - - checkMochaSyntax(diff); -} else { - console.error('Invalid automation type.'); - process.exit(1); -} - -function getPreCommitHookDiff() { - return execSync(`git diff --cached HEAD`).toString().trim(); -} - -function getPrePushHookDiff() { - const currentBranch = execSync(`git rev-parse --abbrev-ref HEAD`) - .toString() - .trim(); - - return execSync( - `git diff ${currentBranch} origin/${currentBranch} -- . ':(exclude)development/fitness-functions/'`, - ) - .toString() - .trim(); -} diff --git a/development/fitness-functions/index.ts b/development/fitness-functions/index.ts new file mode 100644 index 000000000..2cb720d4f --- /dev/null +++ b/development/fitness-functions/index.ts @@ -0,0 +1,11 @@ +import { AUTOMATION_TYPE } from './common/constants'; +import { getDiffByAutomationType } from './common/get-diff'; +import { IRule, RULES, runFitnessFunctionRule } from './rules'; + +const automationType: AUTOMATION_TYPE = process.argv[2] as AUTOMATION_TYPE; + +const diff = getDiffByAutomationType(automationType); + +if (typeof diff === 'string') { + RULES.forEach((rule: IRule): void => runFitnessFunctionRule(rule, diff)); +} diff --git a/development/fitness-functions/rules/index.ts b/development/fitness-functions/rules/index.ts new file mode 100644 index 000000000..30844652c --- /dev/null +++ b/development/fitness-functions/rules/index.ts @@ -0,0 +1,42 @@ +import { preventSinonAssertSyntax } from './sinon-assert-syntax'; +import { preventJavaScriptFileAdditions } from './javascript-additions'; + +const RULES: IRule[] = [ + { + name: "Don't use `sinon` or `assert` in unit tests", + fn: preventSinonAssertSyntax, + docURL: + 'https://github.com/MetaMask/metamask-extension/blob/develop/docs/testing.md#favor-jest-instead-of-mocha', + }, + { + name: "Don't add JS or JSX files to the `shared` directory", + fn: preventJavaScriptFileAdditions, + }, +]; + +interface IRule { + name: string; + fn: (diff: string) => boolean; + docURL?: string; +} + +function runFitnessFunctionRule(rule: IRule, diff: string): void { + const { name, fn, docURL } = rule; + console.log(`Checking rule "${name}"...`); + + const hasRulePassed: boolean = fn(diff) as boolean; + if (hasRulePassed === true) { + console.log(`...OK`); + } else { + console.log(`...FAILED. Changes not accepted by the fitness function.`); + + if (docURL) { + console.log(`For more info: ${docURL}.`); + } + + process.exit(1); + } +} + +export { RULES, runFitnessFunctionRule }; +export type { IRule }; diff --git a/development/fitness-functions/rules/javascript-additions.test.ts b/development/fitness-functions/rules/javascript-additions.test.ts new file mode 100644 index 000000000..db1803c1d --- /dev/null +++ b/development/fitness-functions/rules/javascript-additions.test.ts @@ -0,0 +1,51 @@ +import { + generateModifyFilesDiff, + generateCreateFileDiff, +} from '../common/test-data'; +import { preventJavaScriptFileAdditions } from './javascript-additions'; + +describe('preventJavaScriptFileAdditions()', (): void => { + it('should pass when receiving an empty diff', (): void => { + const testDiff = ''; + + const hasRulePassed = preventJavaScriptFileAdditions(testDiff); + + expect(hasRulePassed).toBe(true); + }); + + it('should pass when receiving a diff with a new TS file on the shared folder', (): void => { + const testDiff = [ + generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), + generateModifyFilesDiff('old-file.js', undefined, 'pong'), + generateCreateFileDiff('shared/test.ts', 'yada yada yada yada'), + ].join(''); + + const hasRulePassed = preventJavaScriptFileAdditions(testDiff); + + expect(hasRulePassed).toBe(true); + }); + + it('should not pass when receiving a diff with a new JS file on the shared folder', (): void => { + const testDiff = [ + generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), + generateModifyFilesDiff('old-file.js', undefined, 'pong'), + generateCreateFileDiff('shared/test.js', 'yada yada yada yada'), + ].join(''); + + const hasRulePassed = preventJavaScriptFileAdditions(testDiff); + + expect(hasRulePassed).toBe(false); + }); + + it('should not pass when receiving a diff with a new JSX file on the shared folder', (): void => { + const testDiff = [ + generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), + generateModifyFilesDiff('old-file.js', undefined, 'pong'), + generateCreateFileDiff('shared/test.jsx', 'yada yada yada yada'), + ].join(''); + + const hasRulePassed = preventJavaScriptFileAdditions(testDiff); + + expect(hasRulePassed).toBe(false); + }); +}); diff --git a/development/fitness-functions/rules/javascript-additions.ts b/development/fitness-functions/rules/javascript-additions.ts new file mode 100644 index 000000000..3e3705ea3 --- /dev/null +++ b/development/fitness-functions/rules/javascript-additions.ts @@ -0,0 +1,18 @@ +import { SHARED_FOLDER_JS_REGEX } from '../common/constants'; +import { + filterDiffByFilePath, + filterDiffFileCreations, +} from '../common/shared'; + +function preventJavaScriptFileAdditions(diff: string): boolean { + const sharedFolderDiff = filterDiffByFilePath(diff, SHARED_FOLDER_JS_REGEX); + const sharedFolderCreationDiff = filterDiffFileCreations(sharedFolderDiff); + + const hasCreatedAtLeastOneJSFileInShared = sharedFolderCreationDiff !== ''; + if (hasCreatedAtLeastOneJSFileInShared) { + return false; + } + return true; +} + +export { preventJavaScriptFileAdditions }; diff --git a/development/fitness-functions/rules/sinon-assert-syntax.test.ts b/development/fitness-functions/rules/sinon-assert-syntax.test.ts new file mode 100644 index 000000000..ea403d4a0 --- /dev/null +++ b/development/fitness-functions/rules/sinon-assert-syntax.test.ts @@ -0,0 +1,29 @@ +import { generateModifyFilesDiff } from '../common/test-data'; +import { preventSinonAssertSyntax } from './sinon-assert-syntax'; + +describe('preventSinonAssertSyntax()', (): void => { + it('should pass when receiving an empty diff', (): void => { + const testDiff = ''; + + const hasRulePassed = preventSinonAssertSyntax(testDiff); + + expect(hasRulePassed).toBe(true); + }); + + it('should not pass when receiving a diff with one of the blocked expressions', (): void => { + const infringingExpression = 'assert.equal'; + const testDiff = [ + generateModifyFilesDiff('new-file.ts', 'foo', 'bar'), + generateModifyFilesDiff('old-file.js', undefined, 'pong'), + generateModifyFilesDiff( + 'test.js', + `yada yada ${infringingExpression} yada yada`, + undefined, + ), + ].join(''); + + const hasRulePassed = preventSinonAssertSyntax(testDiff); + + expect(hasRulePassed).toBe(false); + }); +}); diff --git a/development/fitness-functions/rules/sinon-assert-syntax.ts b/development/fitness-functions/rules/sinon-assert-syntax.ts new file mode 100644 index 000000000..57551f929 --- /dev/null +++ b/development/fitness-functions/rules/sinon-assert-syntax.ts @@ -0,0 +1,30 @@ +import { EXCLUDE_E2E_TESTS_REGEX } from '../common/constants'; +import { + filterDiffLineAdditions, + filterDiffByFilePath, + hasNumberOfCodeBlocksIncreased, +} from '../common/shared'; + +const codeBlocks = [ + "import { strict as assert } from 'assert';", + 'assert.deepEqual', + 'assert.equal', + 'assert.rejects', + 'assert.strictEqual', + 'sinon.', +]; + +function preventSinonAssertSyntax(diff: string): boolean { + const diffByFilePath = filterDiffByFilePath(diff, EXCLUDE_E2E_TESTS_REGEX); + const diffAdditions = filterDiffLineAdditions(diffByFilePath); + const hashmap = hasNumberOfCodeBlocksIncreased(diffAdditions, codeBlocks); + + const haveOccurencesOfAtLeastOneCodeBlockIncreased = + Object.values(hashmap).includes(true); + if (haveOccurencesOfAtLeastOneCodeBlockIncreased) { + return false; + } + return true; +} + +export { preventSinonAssertSyntax }; diff --git a/development/generate-lavamoat-policies.js b/development/generate-lavamoat-policies.js index 9266091b7..16a669f2c 100755 --- a/development/generate-lavamoat-policies.js +++ b/development/generate-lavamoat-policies.js @@ -2,11 +2,13 @@ const concurrently = require('concurrently'); const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); -const { BuildType } = require('./lib/build-type'); +const { loadBuildTypesConfig } = require('./lib/build-type'); -const stableBuildTypes = Object.values(BuildType).filter( +const buildTypesConfig = loadBuildTypesConfig(); + +const stableBuildTypes = Object.keys(buildTypesConfig.buildTypes).filter( // Skip generating policy for MMI until that build has stabilized - (buildType) => buildType !== BuildType.mmi, + (buildType) => buildType !== 'mmi', ); start().catch((error) => { @@ -24,7 +26,7 @@ async function start() { yargsInstance .option('build-types', { alias: ['t'], - choices: Object.values(BuildType), + choices: Object.keys(buildTypesConfig.buildTypes), default: stableBuildTypes, demandOption: true, description: 'The build type(s) to generate policy files for.', diff --git a/development/lib/build-type.d.ts b/development/lib/build-type.d.ts new file mode 100644 index 000000000..dafc9e904 --- /dev/null +++ b/development/lib/build-type.d.ts @@ -0,0 +1,6 @@ +import { Infer, Struct } from 'superstruct'; + +export type Unique> = ( + struct: Struct[], Infer>, + eq?: (a: Infer, b: Infer) => boolean, +) => Struct[], Infer>; diff --git a/development/lib/build-type.js b/development/lib/build-type.js index 762b9af45..afc5401fc 100644 --- a/development/lib/build-type.js +++ b/development/lib/build-type.js @@ -1,18 +1,169 @@ +const fs = require('fs'); +const { AssertionError } = require('assert'); +const path = require('path'); +const { + object, + string, + record, + optional, + array, + refine, + any, + boolean, + coerce, + union, + unknown, + validate, + nullable, + never, +} = require('superstruct'); +const yaml = require('js-yaml'); +const { uniqWith } = require('lodash'); + +const BUILDS_YML_PATH = path.resolve('./builds.yml'); + /** - * The distribution this build is intended for. - * - * This should be kept in-sync with the `BuildType` map in `shared/constants/app.js`. + * @type {import('superstruct').Infer | null} */ -const BuildType = { - beta: 'beta', - desktop: 'desktop', - flask: 'flask', - main: 'main', - mmi: 'mmi', -}; +let cachedBuildTypes = null; -const BuildTypeInheritance = { - [BuildType.desktop]: [BuildType.flask], -}; +/** + * Ensures that the array item contains only elements that are distinct from each other + * + * @template {Struct} Element + * @type {import('./build-type').Unique} + */ +const unique = (struct, eq) => + refine(struct, 'unique', (value) => { + if (uniqWith(value, eq).length === value.length) { + return true; + } + return 'Array contains duplicated values'; + }); -module.exports = { BuildType, BuildTypeInheritance }; +const EnvDefinitionStruct = coerce( + object({ key: string(), value: unknown() }), + refine(record(string(), any()), 'Env variable declaration', (value) => { + if (Object.keys(value).length !== 1) { + return 'Declaration should have only one property, the name'; + } + return true; + }), + (value) => ({ key: Object.keys(value)[0], value: Object.values(value)[0] }), +); + +const EnvArrayStruct = unique( + array(union([string(), EnvDefinitionStruct])), + (a, b) => { + const keyA = typeof a === 'string' ? a : a.key; + const keyB = typeof b === 'string' ? b : b.key; + return keyA === keyB; + }, +); + +const BuildTypeStruct = object({ + features: optional(unique(array(string()))), + env: optional(EnvArrayStruct), + isPrerelease: optional(boolean()), + manifestOverrides: optional(string()), +}); + +const CopyAssetStruct = object({ src: string(), dest: string() }); +const ExclusiveIncludeAssetStruct = coerce( + object({ exclusiveInclude: string() }), + string(), + (exclusiveInclude) => ({ exclusiveInclude }), +); +const AssetStruct = union([CopyAssetStruct, ExclusiveIncludeAssetStruct]); + +const FeatureStruct = object({ + env: optional(EnvArrayStruct), + // TODO(ritave): Check if the paths exist + assets: optional(array(AssetStruct)), +}); + +const FeaturesStruct = refine( + record( + string(), + coerce(FeatureStruct, nullable(never()), () => ({})), + ), + 'feature definitions', + function* (value) { + let isValid = true; + + const definitions = new Set(); + + for (const feature of Object.values(value)) { + for (const env of feature?.env ?? []) { + if (typeof env !== 'string') { + if (definitions.has(env.key)) { + isValid = false; + yield `Multiple defined features have a definition of "${env}" env variable, resulting in a conflict`; + } + definitions.add(env.key); + } + } + } + return isValid; + }, +); + +const BuildTypesStruct = refine( + object({ + default: string(), + buildTypes: record(string(), BuildTypeStruct), + features: FeaturesStruct, + env: EnvArrayStruct, + }), + 'BuildTypes', + (value) => { + if (!Object.keys(value.buildTypes).includes(value.default)) { + return `Default build type "${value.default}" does not exist in builds declarations`; + } + return true; + }, +); + +/** + * Loads definitions of build type and what they are composed of. + * + * @returns {import('superstruct').Infer} + */ +function loadBuildTypesConfig() { + if (cachedBuildTypes !== null) { + return cachedBuildTypes; + } + const buildsData = yaml.load(fs.readFileSync(BUILDS_YML_PATH, 'utf8'), { + json: true, + }); + const [err, result] = validate(buildsData, BuildTypesStruct, { + coerce: true, + }); + if (err !== undefined) { + throw new AssertionError({ + message: constructFailureMessage(err), + }); + } + cachedBuildTypes = result; + return buildsData; +} + +/** + * Creates a user readable error message about parse failure. + * + * @param {import('superstruct').StructError} structError + * @returns {string} + */ +function constructFailureMessage(structError) { + return `Failed to parse builds.yml + -> ${structError + .failures() + .map( + (failure) => + `${failure.message} (${BUILDS_YML_PATH}:.${failure.path.join('/')})`, + ) + .join('\n -> ')} +`; +} + +module.exports = { loadBuildTypesConfig }; diff --git a/development/lib/get-version.js b/development/lib/get-version.js index 9f787265f..ec40b40cb 100644 --- a/development/lib/get-version.js +++ b/development/lib/get-version.js @@ -1,5 +1,5 @@ const { version: manifestVersion } = require('../../package.json'); -const { BuildType } = require('./build-type'); +const { loadBuildTypesConfig } = require('./build-type'); /** * Get the current version of the MetaMask extension. The base manifest version @@ -8,14 +8,14 @@ const { BuildType } = require('./build-type'); * The build version is needed because certain build types (such as beta) may * be released multiple times during the release process. * - * @param {BuildType} buildType - The build type. + * @param {string} buildType - The build type. * @param {number} buildVersion - The build version. * @returns {string} The MetaMask extension version. */ function getVersion(buildType, buildVersion) { - return buildType === BuildType.main || buildType === BuildType.beta - ? manifestVersion - : `${manifestVersion}-${buildType}.${buildVersion}`; + return loadBuildTypesConfig().buildTypes[buildType].isPrerelease === true + ? `${manifestVersion}-${buildType}.${buildVersion}` + : manifestVersion; } module.exports = { getVersion }; diff --git a/development/lib/variables.js b/development/lib/variables.js new file mode 100644 index 000000000..b2fb61212 --- /dev/null +++ b/development/lib/variables.js @@ -0,0 +1,114 @@ +/* eslint-disable jsdoc/check-tag-names */ +const assert = require('assert'); + +const DeclaredOnly = Symbol( + 'This variable was declared only without being defined', +); + +class Variables { + /** + * @type {Map} + */ + #definitions = new Map(); + + /** + * @param {Iterable} declarations + */ + constructor(declarations) { + for (const declaration of declarations) { + this.#definitions.set(declaration, DeclaredOnly); + } + } + + /** + * @param {string} key - The name of the variable + * @throws {TypeError} If there is no definition of a variable. + */ + get(key) { + const value = this.getMaybe(key); + assert( + value !== DeclaredOnly, + new TypeError( + `Tried to access a declared, but not defined environmental variable "${key}"`, + ), + ); + return value; + } + + /** + * Returns a declared, but maybe not defined variable. + * + * @param {string} key - The name of the variable + * @throws {TypeError} If there was no declaration of the variable. + * @returns The value, or undefined if the variables wasn't defined. + */ + getMaybe(key) { + assert( + this.isDeclared(key), + new TypeError( + `Tried to access an environmental variable "${key}" that wasn't declared in builds.yml`, + ), + ); + return this.#definitions.get(key); + } + + /** + * Sets one key + * + * @overload + * @param {string} key + * @param {unknown} value + * @returns {void} + */ + /** + * @overload + * @param {Record} records - Key-Value object + * @returns {void} + */ + /** + * @param {string | Record} keyOrRecord + * @param {unknown} value + * @returns {void} + */ + set(keyOrRecord, value) { + if (typeof keyOrRecord === 'object') { + for (const [key, recordValue] of Object.entries(keyOrRecord)) { + this.set(key, recordValue); + } + return; + } + const key = keyOrRecord; + assert( + this.isDeclared(key), + `Tried to modify a variable "${key}" that wasn't declared in builds.yml`, + ); + assert(value !== DeclaredOnly, `Tried to un-define "${key}" variable`); + this.#definitions.set(key, value); + } + + isDeclared(key) { + return this.#definitions.has(key); + } + + isDefined(key) { + return ( + this.#definitions.has(key) && this.#definitions.get(key) !== DeclaredOnly + ); + } + + [Symbol.iterator] = this.declarations; + + *declarations() { + yield* this.#definitions.keys(); + } + + *definitions() { + for (const [key, value] of this.#definitions.entries()) { + if (value !== DeclaredOnly) { + yield [key, value]; + } + } + } +} + +module.exports = { Variables }; diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index 028298e80..729f2ce5b 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -45,12 +45,7 @@ async function start() { return `${platform}`; }) .join(', '); - const betaBuildLinks = platforms - .map((platform) => { - const url = `${BUILD_LINK_BASE}/builds-beta/metamask-beta-${platform}-${VERSION}.zip`; - return `${platform}`; - }) - .join(', '); + const betaBuildLinks = `chrome`; const flaskBuildLinks = platforms .map((platform) => { const url = `${BUILD_LINK_BASE}/builds-flask/metamask-flask-${platform}-${VERSION}-flask.0.zip`; diff --git a/development/sentry-publish.js b/development/sentry-publish.js index 5a988c65b..3645e04b6 100755 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -5,7 +5,7 @@ const { hideBin } = require('yargs/helpers'); const { runCommand, runInShell } = require('./lib/run-command'); const { getVersion } = require('./lib/get-version'); -const { BuildType } = require('./lib/build-type'); +const { loadBuildTypesConfig } = require('./lib/build-type'); start().catch((error) => { console.error(error); @@ -29,9 +29,9 @@ async function start() { type: 'string', }) .option('build-type', { - default: BuildType.main, + default: loadBuildTypesConfig().default, description: 'The MetaMask extension build type', - choices: Object.values(BuildType), + choices: Object.keys(loadBuildTypesConfig().buildTypes), }) .option('build-version', { default: 0, @@ -86,7 +86,7 @@ async function start() { } const additionalUploadArgs = []; - if (buildType !== BuildType.main) { + if (buildType !== loadBuildTypesConfig().default) { additionalUploadArgs.push('--dist-directory', `dist-${buildType}`); } // upload sentry source and sourcemaps diff --git a/development/states/navigate-txs.json b/development/states/navigate-txs.json index 6a4605e9a..12fc75607 100644 --- a/development/states/navigate-txs.json +++ b/development/states/navigate-txs.json @@ -225,7 +225,7 @@ "preferences": { "useETHAsPrimaryCurrency": true }, - "provider": { + "providerConfig": { "type": "goerli" }, "network": "4", diff --git a/development/ts-migration-dashboard/files-to-convert.json b/development/ts-migration-dashboard/files-to-convert.json index 713f53ff7..bf123f1e3 100644 --- a/development/ts-migration-dashboard/files-to-convert.json +++ b/development/ts-migration-dashboard/files-to-convert.json @@ -79,8 +79,6 @@ "app/scripts/lib/createRPCMethodTrackingMiddleware.test.js", "app/scripts/lib/createStreamSink.js", "app/scripts/lib/createTabIdMiddleware.js", - "app/scripts/lib/decrypt-message-manager.js", - "app/scripts/lib/encryption-public-key-manager.js", "app/scripts/lib/ens-ipfs/contracts/registry.js", "app/scripts/lib/ens-ipfs/contracts/resolver.js", "app/scripts/lib/ens-ipfs/resolver.js", diff --git a/development/ts-migration-dashboard/scripts/build-app.ts b/development/ts-migration-dashboard/scripts/build-app.ts index 95a74221c..1e1d6fcd3 100644 --- a/development/ts-migration-dashboard/scripts/build-app.ts +++ b/development/ts-migration-dashboard/scripts/build-app.ts @@ -8,7 +8,8 @@ import pify from 'pify'; import endOfStream from 'end-of-stream'; import pump from 'pump'; import gulp from 'gulp'; -import gulpDartSass from 'gulp-dart-sass'; +import gulpSass from 'gulp-sass'; +import sass from 'sass'; import sourcemaps from 'gulp-sourcemaps'; import autoprefixer from 'gulp-autoprefixer'; import fg from 'fast-glob'; @@ -94,7 +95,7 @@ async function compileStylesheets(src: string, dest: string): Promise { await promisifiedPump( gulp.src(src), sourcemaps.init(), - gulpDartSass().on('error', (error: unknown) => { + gulpSass(sass)().on('error', (error: unknown) => { console.error(`Couldn't compile stylesheets: ${error}`); }), autoprefixer(), diff --git a/jest.config.js b/jest.config.js index bbcb93a4a..a3813632b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,6 +6,7 @@ module.exports = { '!/app/scripts/controllers/network/**/test/*.ts', '/app/scripts/controllers/permissions/**/*.js', '/app/scripts/controllers/sign.ts', + '/app/scripts/controllers/decrypt-message.ts', '/app/scripts/flask/**/*.js', '/app/scripts/lib/**/*.js', '/app/scripts/lib/createRPCMethodTrackingMiddleware.js', @@ -44,6 +45,7 @@ module.exports = { '/app/scripts/controllers/network/**/*.test.ts', '/app/scripts/controllers/permissions/**/*.test.js', '/app/scripts/controllers/sign.test.ts', + '/app/scripts/controllers/decrypt-message.test.ts', '/app/scripts/flask/**/*.test.js', '/app/scripts/lib/**/*.test.js', '/app/scripts/lib/**/*.test.ts', diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json index 41d9cfc47..6d049fb83 100644 --- a/lavamoat/browserify/beta/policy.json +++ b/lavamoat/browserify/beta/policy.json @@ -687,6 +687,7 @@ "URL": true, "clearInterval": true, "clearTimeout": true, + "console.error": true, "console.info": true, "console.log": true, "setInterval": true, @@ -696,13 +697,13 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/assets-controllers>@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/utils": true, "@metamask/assets-controllers>abort-controller": true, "@metamask/assets-controllers>multiformats": true, "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/metamask-eth-abis": true, + "@metamask/utils": true, "browserify>events": true, "eth-json-rpc-filters>async-mutex": true, "eth-query": true, @@ -715,7 +716,7 @@ "@metamask/assets-controllers>@metamask/abi-utils": { "packages": { "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": { @@ -724,22 +725,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true - } - }, - "@metamask/assets-controllers>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/assets-controllers>abort-controller": { @@ -761,13 +750,14 @@ }, "@metamask/controller-utils": { "globals": { + "URL": true, "console.error": true, "fetch": true, "setTimeout": true }, "packages": { - "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, + "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -775,18 +765,6 @@ "ethjs>ethjs-unit": true } }, - "@metamask/controller-utils>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -805,11 +783,6 @@ "browserify>insert-module-globals>is-buffer": true } }, - "@metamask/controllers>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/controllers>web3": { "globals": { "XMLHttpRequest": true @@ -843,10 +816,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -891,10 +864,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-provider": { @@ -1214,10 +1187,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/key-tree>@noble/ed25519": { @@ -1339,7 +1312,12 @@ "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true } }, "@metamask/rpc-methods>@metamask/browser-passworder": { @@ -1449,6 +1427,11 @@ "setTimeout": true } }, + "@metamask/snaps-controllers-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-controllers>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1465,10 +1448,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/utils>@ethereumjs/tx>@chainsafe/ssz": { @@ -2681,10 +2664,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "eth-ens-namehash": { @@ -2802,7 +2785,6 @@ "@ethersproject/abi": true, "bn.js": true, "browserify>buffer": true, - "browserify>process": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/common": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/tx": true, "eth-lattice-keyring>gridplus-sdk>bech32": true, diff --git a/lavamoat/browserify/desktop/policy.json b/lavamoat/browserify/desktop/policy.json index 140cf85f0..6386fa0b8 100644 --- a/lavamoat/browserify/desktop/policy.json +++ b/lavamoat/browserify/desktop/policy.json @@ -687,6 +687,7 @@ "URL": true, "clearInterval": true, "clearTimeout": true, + "console.error": true, "console.info": true, "console.log": true, "setInterval": true, @@ -696,13 +697,13 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/assets-controllers>@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/utils": true, "@metamask/assets-controllers>abort-controller": true, "@metamask/assets-controllers>multiformats": true, "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/metamask-eth-abis": true, + "@metamask/utils": true, "browserify>events": true, "eth-json-rpc-filters>async-mutex": true, "eth-query": true, @@ -715,7 +716,7 @@ "@metamask/assets-controllers>@metamask/abi-utils": { "packages": { "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": { @@ -724,22 +725,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true - } - }, - "@metamask/assets-controllers>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/assets-controllers>abort-controller": { @@ -761,13 +750,14 @@ }, "@metamask/controller-utils": { "globals": { + "URL": true, "console.error": true, "fetch": true, "setTimeout": true }, "packages": { - "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, + "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -775,18 +765,6 @@ "ethjs>ethjs-unit": true } }, - "@metamask/controller-utils>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -805,11 +783,6 @@ "browserify>insert-module-globals>is-buffer": true } }, - "@metamask/controllers>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/controllers>web3": { "globals": { "XMLHttpRequest": true @@ -849,7 +822,6 @@ "@metamask/desktop>otpauth": true, "browserify>buffer": true, "browserify>events": true, - "browserify>process": true, "browserify>stream-browserify": true, "end-of-stream": true, "extension-port-stream": true, @@ -915,10 +887,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -963,10 +935,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-provider": { @@ -1286,10 +1258,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/key-tree>@noble/ed25519": { @@ -1436,10 +1408,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/post-message-stream>readable-stream": { @@ -1501,8 +1473,27 @@ "@metamask/snaps-ui": true, "@metamask/snaps-utils": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true, - "eth-rpc-errors": true + "eth-rpc-errors": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask": { + "packages": { + "@metamask/key-tree": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/permission-controller": true, + "@metamask/rpc-methods-flask>nanoid": true, + "@metamask/rpc-methods>@metamask/browser-passworder": true, + "@metamask/snaps-ui": true, + "@metamask/snaps-utils": true, + "@metamask/utils": true, + "eth-rpc-errors": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true } }, "@metamask/rpc-methods>@metamask/browser-passworder": { @@ -1612,7 +1603,7 @@ "setTimeout": true } }, - "@metamask/snaps-controllers": { + "@metamask/snaps-controllers-flask": { "globals": { "URL": true, "chrome.offscreen.createDocument": true, @@ -1628,10 +1619,10 @@ "@metamask/post-message-stream": true, "@metamask/providers>@metamask/object-multiplex": true, "@metamask/rpc-methods": true, + "@metamask/snaps-controllers-flask>concat-stream": true, + "@metamask/snaps-controllers-flask>nanoid": true, "@metamask/snaps-controllers>@xstate/fsm": true, - "@metamask/snaps-controllers>concat-stream": true, "@metamask/snaps-controllers>gunzip-maybe": true, - "@metamask/snaps-controllers>nanoid": true, "@metamask/snaps-controllers>readable-web-to-node-stream": true, "@metamask/snaps-controllers>tar-stream": true, "@metamask/snaps-utils": true, @@ -1644,14 +1635,14 @@ "pump": true } }, - "@metamask/snaps-controllers>concat-stream": { + "@metamask/snaps-controllers-flask>concat-stream": { "packages": { - "@metamask/snaps-controllers>concat-stream>readable-stream": true, + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": true, "browserify>buffer": true, "pumpify>inherits": true } }, - "@metamask/snaps-controllers>concat-stream>readable-stream": { + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": { "packages": { "@storybook/api>util-deprecate": true, "browserify>browser-resolve": true, @@ -1662,6 +1653,11 @@ "pumpify>inherits": true } }, + "@metamask/snaps-controllers-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-controllers>gunzip-maybe": { "packages": { "@metamask/snaps-controllers>gunzip-maybe>browserify-zlib": true, @@ -1793,7 +1789,13 @@ "@metamask/snaps-ui": { "packages": { "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true + } + }, + "@metamask/snaps-ui-flask": { + "packages": { + "@metamask/utils": true, + "superstruct": true } }, "@metamask/snaps-utils": { @@ -1814,15 +1816,37 @@ "@metamask/snaps-utils>rfdc": true, "@metamask/snaps-utils>validate-npm-package-name": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true, - "semver": true + "semver": true, + "superstruct": true + } + }, + "@metamask/snaps-utils-flask": { + "globals": { + "TextDecoder": true, + "URL": true, + "console.error": true, + "console.log": true, + "console.warn": true, + "document.body.appendChild": true, + "document.createElement": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, + "@metamask/snaps-utils>cron-parser": true, + "@metamask/snaps-utils>fast-json-stable-stringify": true, + "@metamask/snaps-utils>rfdc": true, + "@metamask/snaps-utils>validate-npm-package-name": true, + "@metamask/utils": true, + "semver": true, + "superstruct": true } }, "@metamask/snaps-utils>@metamask/snaps-registry": { "packages": { "@metamask/key-tree>@noble/secp256k1": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/snaps-utils>cron-parser": { @@ -1858,10 +1882,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/utils>@ethereumjs/tx>@chainsafe/ssz": { @@ -3074,10 +3098,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "eth-ens-namehash": { @@ -3195,7 +3219,6 @@ "@ethersproject/abi": true, "bn.js": true, "browserify>buffer": true, - "browserify>process": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/common": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/tx": true, "eth-lattice-keyring>gridplus-sdk>bech32": true, diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json index 140cf85f0..6386fa0b8 100644 --- a/lavamoat/browserify/flask/policy.json +++ b/lavamoat/browserify/flask/policy.json @@ -687,6 +687,7 @@ "URL": true, "clearInterval": true, "clearTimeout": true, + "console.error": true, "console.info": true, "console.log": true, "setInterval": true, @@ -696,13 +697,13 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/assets-controllers>@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/utils": true, "@metamask/assets-controllers>abort-controller": true, "@metamask/assets-controllers>multiformats": true, "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/metamask-eth-abis": true, + "@metamask/utils": true, "browserify>events": true, "eth-json-rpc-filters>async-mutex": true, "eth-query": true, @@ -715,7 +716,7 @@ "@metamask/assets-controllers>@metamask/abi-utils": { "packages": { "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": { @@ -724,22 +725,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true - } - }, - "@metamask/assets-controllers>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/assets-controllers>abort-controller": { @@ -761,13 +750,14 @@ }, "@metamask/controller-utils": { "globals": { + "URL": true, "console.error": true, "fetch": true, "setTimeout": true }, "packages": { - "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, + "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -775,18 +765,6 @@ "ethjs>ethjs-unit": true } }, - "@metamask/controller-utils>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -805,11 +783,6 @@ "browserify>insert-module-globals>is-buffer": true } }, - "@metamask/controllers>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/controllers>web3": { "globals": { "XMLHttpRequest": true @@ -849,7 +822,6 @@ "@metamask/desktop>otpauth": true, "browserify>buffer": true, "browserify>events": true, - "browserify>process": true, "browserify>stream-browserify": true, "end-of-stream": true, "extension-port-stream": true, @@ -915,10 +887,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -963,10 +935,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-provider": { @@ -1286,10 +1258,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/key-tree>@noble/ed25519": { @@ -1436,10 +1408,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/post-message-stream>readable-stream": { @@ -1501,8 +1473,27 @@ "@metamask/snaps-ui": true, "@metamask/snaps-utils": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true, - "eth-rpc-errors": true + "eth-rpc-errors": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask": { + "packages": { + "@metamask/key-tree": true, + "@metamask/key-tree>@noble/hashes": true, + "@metamask/permission-controller": true, + "@metamask/rpc-methods-flask>nanoid": true, + "@metamask/rpc-methods>@metamask/browser-passworder": true, + "@metamask/snaps-ui": true, + "@metamask/snaps-utils": true, + "@metamask/utils": true, + "eth-rpc-errors": true, + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true } }, "@metamask/rpc-methods>@metamask/browser-passworder": { @@ -1612,7 +1603,7 @@ "setTimeout": true } }, - "@metamask/snaps-controllers": { + "@metamask/snaps-controllers-flask": { "globals": { "URL": true, "chrome.offscreen.createDocument": true, @@ -1628,10 +1619,10 @@ "@metamask/post-message-stream": true, "@metamask/providers>@metamask/object-multiplex": true, "@metamask/rpc-methods": true, + "@metamask/snaps-controllers-flask>concat-stream": true, + "@metamask/snaps-controllers-flask>nanoid": true, "@metamask/snaps-controllers>@xstate/fsm": true, - "@metamask/snaps-controllers>concat-stream": true, "@metamask/snaps-controllers>gunzip-maybe": true, - "@metamask/snaps-controllers>nanoid": true, "@metamask/snaps-controllers>readable-web-to-node-stream": true, "@metamask/snaps-controllers>tar-stream": true, "@metamask/snaps-utils": true, @@ -1644,14 +1635,14 @@ "pump": true } }, - "@metamask/snaps-controllers>concat-stream": { + "@metamask/snaps-controllers-flask>concat-stream": { "packages": { - "@metamask/snaps-controllers>concat-stream>readable-stream": true, + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": true, "browserify>buffer": true, "pumpify>inherits": true } }, - "@metamask/snaps-controllers>concat-stream>readable-stream": { + "@metamask/snaps-controllers-flask>concat-stream>readable-stream": { "packages": { "@storybook/api>util-deprecate": true, "browserify>browser-resolve": true, @@ -1662,6 +1653,11 @@ "pumpify>inherits": true } }, + "@metamask/snaps-controllers-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-controllers>gunzip-maybe": { "packages": { "@metamask/snaps-controllers>gunzip-maybe>browserify-zlib": true, @@ -1793,7 +1789,13 @@ "@metamask/snaps-ui": { "packages": { "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true + } + }, + "@metamask/snaps-ui-flask": { + "packages": { + "@metamask/utils": true, + "superstruct": true } }, "@metamask/snaps-utils": { @@ -1814,15 +1816,37 @@ "@metamask/snaps-utils>rfdc": true, "@metamask/snaps-utils>validate-npm-package-name": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true, - "semver": true + "semver": true, + "superstruct": true + } + }, + "@metamask/snaps-utils-flask": { + "globals": { + "TextDecoder": true, + "URL": true, + "console.error": true, + "console.log": true, + "console.warn": true, + "document.body.appendChild": true, + "document.createElement": true + }, + "packages": { + "@metamask/key-tree>@noble/hashes": true, + "@metamask/key-tree>@scure/base": true, + "@metamask/snaps-utils>cron-parser": true, + "@metamask/snaps-utils>fast-json-stable-stringify": true, + "@metamask/snaps-utils>rfdc": true, + "@metamask/snaps-utils>validate-npm-package-name": true, + "@metamask/utils": true, + "semver": true, + "superstruct": true } }, "@metamask/snaps-utils>@metamask/snaps-registry": { "packages": { "@metamask/key-tree>@noble/secp256k1": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/snaps-utils>cron-parser": { @@ -1858,10 +1882,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/utils>@ethereumjs/tx>@chainsafe/ssz": { @@ -3074,10 +3098,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "eth-ens-namehash": { @@ -3195,7 +3219,6 @@ "@ethersproject/abi": true, "bn.js": true, "browserify>buffer": true, - "browserify>process": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/common": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/tx": true, "eth-lattice-keyring>gridplus-sdk>bech32": true, diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json index 41d9cfc47..6d049fb83 100644 --- a/lavamoat/browserify/main/policy.json +++ b/lavamoat/browserify/main/policy.json @@ -687,6 +687,7 @@ "URL": true, "clearInterval": true, "clearTimeout": true, + "console.error": true, "console.info": true, "console.log": true, "setInterval": true, @@ -696,13 +697,13 @@ "@ethersproject/contracts": true, "@ethersproject/providers": true, "@metamask/assets-controllers>@metamask/abi-utils": true, - "@metamask/assets-controllers>@metamask/utils": true, "@metamask/assets-controllers>abort-controller": true, "@metamask/assets-controllers>multiformats": true, "@metamask/base-controller": true, "@metamask/contract-metadata": true, "@metamask/controller-utils": true, "@metamask/metamask-eth-abis": true, + "@metamask/utils": true, "browserify>events": true, "eth-json-rpc-filters>async-mutex": true, "eth-query": true, @@ -715,7 +716,7 @@ "@metamask/assets-controllers>@metamask/abi-utils": { "packages": { "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true } }, "@metamask/assets-controllers>@metamask/abi-utils>@metamask/utils": { @@ -724,22 +725,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true - } - }, - "@metamask/assets-controllers>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/assets-controllers>abort-controller": { @@ -761,13 +750,14 @@ }, "@metamask/controller-utils": { "globals": { + "URL": true, "console.error": true, "fetch": true, "setTimeout": true }, "packages": { - "@metamask/controller-utils>@metamask/utils": true, "@metamask/controller-utils>@spruceid/siwe-parser": true, + "@metamask/utils": true, "browserify>buffer": true, "eslint>fast-deep-equal": true, "eth-ens-namehash": true, @@ -775,18 +765,6 @@ "ethjs>ethjs-unit": true } }, - "@metamask/controller-utils>@metamask/utils": { - "globals": { - "TextDecoder": true, - "TextEncoder": true - }, - "packages": { - "@metamask/utils>superstruct": true, - "browserify>buffer": true, - "nock>debug": true, - "semver": true - } - }, "@metamask/controller-utils>@spruceid/siwe-parser": { "globals": { "console.error": true, @@ -805,11 +783,6 @@ "browserify>insert-module-globals>is-buffer": true } }, - "@metamask/controllers>nanoid": { - "globals": { - "crypto.getRandomValues": true - } - }, "@metamask/controllers>web3": { "globals": { "XMLHttpRequest": true @@ -843,10 +816,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": { @@ -891,10 +864,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/eth-json-rpc-provider": { @@ -1214,10 +1187,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/key-tree>@noble/ed25519": { @@ -1339,7 +1312,12 @@ "@metamask/key-tree": true, "@metamask/key-tree>@noble/hashes": true, "@metamask/utils": true, - "@metamask/utils>superstruct": true + "superstruct": true + } + }, + "@metamask/rpc-methods-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true } }, "@metamask/rpc-methods>@metamask/browser-passworder": { @@ -1449,6 +1427,11 @@ "setTimeout": true } }, + "@metamask/snaps-controllers-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/snaps-controllers>nanoid": { "globals": { "crypto.getRandomValues": true @@ -1465,10 +1448,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "@metamask/utils>@ethereumjs/tx>@chainsafe/ssz": { @@ -2681,10 +2664,10 @@ "TextEncoder": true }, "packages": { - "@metamask/utils>superstruct": true, "browserify>buffer": true, "nock>debug": true, - "semver": true + "semver": true, + "superstruct": true } }, "eth-ens-namehash": { @@ -2802,7 +2785,6 @@ "@ethersproject/abi": true, "bn.js": true, "browserify>buffer": true, - "browserify>process": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/common": true, "eth-lattice-keyring>gridplus-sdk>@ethereumjs/tx": true, "eth-lattice-keyring>gridplus-sdk>bech32": true, diff --git a/lavamoat/browserify/policy-override.json b/lavamoat/browserify/policy-override.json index 163890952..03d34c1f9 100644 --- a/lavamoat/browserify/policy-override.json +++ b/lavamoat/browserify/policy-override.json @@ -123,12 +123,17 @@ "crypto.getRandomValues": true } }, + "@metamask/snaps-controllers-flask>nanoid": { + "globals": { + "crypto.getRandomValues": true + } + }, "@metamask/rpc-methods>nanoid": { "globals": { "crypto.getRandomValues": true } }, - "@metamask/controllers>nanoid": { + "@metamask/rpc-methods-flask>nanoid": { "globals": { "crypto.getRandomValues": true } diff --git a/lavamoat/build-system/policy-override.json b/lavamoat/build-system/policy-override.json index 7be6fae64..895e28eae 100644 --- a/lavamoat/build-system/policy-override.json +++ b/lavamoat/build-system/policy-override.json @@ -94,6 +94,7 @@ "eslint-plugin-jest>@typescript-eslint/utils>@typescript-eslint/types": true, "eslint-plugin-jest>@typescript-eslint/utils>@typescript-eslint/scope-manager": true, "eslint-plugin-jest>@typescript-eslint/utils>webpack>eslint-scope": true, + "eslint-plugin-mocha>eslint-utils": true, "@typescript-eslint/parser>@typescript-eslint/types": true, "eslint": true, "@typescript-eslint/parser>@typescript-eslint/scope-manager": true, @@ -110,12 +111,18 @@ "eslint>eslint-visitor-keys": true } }, + "eslint-plugin-mocha>eslint-utils": { + "packages": { + "eslint-plugin-mocha>eslint-utils>eslint-visitor-keys": true + } + }, "@typescript-eslint/eslint-plugin>@typescript-eslint/utils": { "builtin": { "path": true }, "packages": { "eslint>eslint-utils": true, + "eslint-plugin-mocha>eslint-utils": true, "@typescript-eslint/parser>@typescript-eslint/types": true, "eslint": true, "@typescript-eslint/parser>@typescript-eslint/scope-manager": true, diff --git a/lavamoat/build-system/policy.json b/lavamoat/build-system/policy.json index 11a78a286..211f6476c 100644 --- a/lavamoat/build-system/policy.json +++ b/lavamoat/build-system/policy.json @@ -1215,6 +1215,7 @@ "@typescript-eslint/parser>@typescript-eslint/types": true, "@typescript-eslint/utils": true, "eslint": true, + "eslint-plugin-mocha>eslint-utils": true, "eslint>eslint-utils": true, "webpack>eslint-scope": true } @@ -1272,14 +1273,148 @@ "typescript": true } }, - "addons-linter>postcss>picocolors": { + "addons-linter>postcss": { "builtin": { - "tty.isatty": true + "fs.existsSync": true, + "fs.readFileSync": true, + "path.dirname": true, + "path.isAbsolute": true, + "path.join": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true, + "url.fileURLToPath": true, + "url.pathToFileURL": true }, "globals": { - "process.argv.includes": true, - "process.env": true, + "Buffer": true, + "URL": true, + "atob": true, + "btoa": true, + "console": true, + "process.env.LANG": true, + "process.env.NODE_ENV": true + }, + "packages": { + "addons-linter>postcss>nanoid": true, + "addons-linter>postcss>source-map-js": true, + "gulp-sass>picocolors": true + } + }, + "babel-plugin-module-resolver": { + "builtin": { + "fs": true, + "path": true + }, + "globals": { + "console.warn": true, + "process.cwd": true, + "process.env.NODE_ENV": true + }, + "packages": { + "babel-plugin-module-resolver>find-babel-config": true, + "babel-plugin-module-resolver>glob": true, + "babel-plugin-module-resolver>pkg-up": true, + "babel-plugin-module-resolver>reselect": true, + "brfs>resolve": true + } + }, + "babel-plugin-module-resolver>find-babel-config": { + "builtin": { + "fs.readFile": true, + "fs.readFileSync": true, + "path.dirname": true, + "path.isAbsolute": true, + "path.join": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "depcheck>json5": true, + "nyc>find-up>path-exists": true + } + }, + "babel-plugin-module-resolver>glob": { + "builtin": { + "assert": true, + "events.EventEmitter": true, + "fs": true, + "path.isAbsolute": true, + "path.join": true, + "path.resolve": true, + "util": true + }, + "globals": { + "console.error": true, + "process.cwd": true, + "process.nextTick": true, "process.platform": true + }, + "packages": { + "babel-plugin-module-resolver>glob>minimatch": true, + "nyc>glob>fs.realpath": true, + "nyc>glob>inflight": true, + "pump>once": true, + "pumpify>inherits": true + } + }, + "babel-plugin-module-resolver>glob>minimatch": { + "globals": { + "console.error": true, + "process": true + }, + "packages": { + "babel-plugin-module-resolver>glob>minimatch>brace-expansion": true + } + }, + "babel-plugin-module-resolver>glob>minimatch>brace-expansion": { + "packages": { + "stylelint>balanced-match": true + } + }, + "babel-plugin-module-resolver>pkg-up": { + "packages": { + "babel-plugin-module-resolver>pkg-up>find-up": true + } + }, + "babel-plugin-module-resolver>pkg-up>find-up": { + "builtin": { + "path.dirname": true, + "path.join": true, + "path.parse": true, + "path.resolve": true + }, + "packages": { + "babel-plugin-module-resolver>pkg-up>find-up>locate-path": true + } + }, + "babel-plugin-module-resolver>pkg-up>find-up>locate-path": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>p-locate": true, + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>path-exists": true + } + }, + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>p-locate": { + "packages": { + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>p-locate>p-limit": true + } + }, + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>p-locate>p-limit": { + "packages": { + "nyc>find-up>locate-path>p-locate>p-limit>p-try": true + } + }, + "babel-plugin-module-resolver>pkg-up>find-up>locate-path>path-exists": { + "builtin": { + "fs.access": true, + "fs.accessSync": true } }, "babelify": { @@ -1400,7 +1535,7 @@ "process.getuid": true, "process.nextTick": true, "process.platform": true, - "process.versions": true + "process.versions.pnp": true }, "packages": { "brfs>resolve>path-parse": true, @@ -1926,10 +2061,10 @@ "packages": { "chokidar>braces": true, "chokidar>fsevents": true, - "chokidar>glob-parent": true, "chokidar>is-binary-path": true, "chokidar>normalize-path": true, "depcheck>readdirp": true, + "eslint>glob-parent": true, "eslint>is-glob": true, "watchify>anymatch": true } @@ -1959,15 +2094,6 @@ }, "native": true }, - "chokidar>glob-parent": { - "builtin": { - "os.platform": true, - "path.posix.dirname": true - }, - "packages": { - "eslint>is-glob": true - } - }, "chokidar>is-binary-path": { "builtin": { "path.extname": true @@ -1976,6 +2102,11 @@ "chokidar>is-binary-path>binary-extensions": true } }, + "copy-webpack-plugin>p-limit": { + "packages": { + "copy-webpack-plugin>p-limit>yocto-queue": true + } + }, "cross-spawn": { "builtin": { "child_process.spawn": true, @@ -2248,19 +2379,23 @@ "assert": true, "fs.existsSync": true, "fs.lstatSync": true, + "fs.promises": true, "fs.readFileSync": true, "fs.readdirSync": true, "fs.statSync": true, "fs.unlinkSync": true, "fs.writeFile": true, "fs.writeFileSync": true, + "path.dirname": true, "path.extname": true, "path.isAbsolute": true, "path.join": true, "path.normalize": true, + "path.posix.join": true, "path.relative": true, "path.resolve": true, "path.sep": true, + "url.pathToFileURL": true, "util.format": true, "util.inspect": true, "util.promisify": true @@ -2273,31 +2408,36 @@ "process": true }, "packages": { + "eslint>@eslint-community/eslint-utils": true, + "eslint>@eslint-community/regexpp": true, "eslint>@eslint/eslintrc": true, + "eslint>@eslint/js": true, "eslint>@humanwhocodes/config-array": true, + "eslint>@nodelib/fs.walk": true, "eslint>ajv": true, "eslint>doctrine": true, "eslint>escape-string-regexp": true, "eslint>eslint-scope": true, - "eslint>eslint-utils": true, "eslint>eslint-visitor-keys": true, "eslint>espree": true, "eslint>esquery": true, "eslint>esutils": true, "eslint>fast-deep-equal": true, "eslint>file-entry-cache": true, - "eslint>functional-red-black-tree": true, "eslint>glob-parent": true, "eslint>globals": true, + "eslint>grapheme-splitter": true, "eslint>imurmurhash": true, "eslint>is-glob": true, + "eslint>is-path-inside": true, + "eslint>js-sdsl": true, "eslint>json-stable-stringify-without-jsonify": true, "eslint>levn": true, "eslint>lodash.merge": true, "eslint>minimatch": true, "eslint>natural-compare": true, - "eslint>regexpp": true, "globby>ignore": true, + "mocha>find-up": true, "nock>debug": true } }, @@ -2573,6 +2713,7 @@ "eslint-plugin-jest>@typescript-eslint/utils>@typescript-eslint/types": true, "eslint-plugin-jest>@typescript-eslint/utils>eslint-utils": true, "eslint-plugin-jest>@typescript-eslint/utils>webpack>eslint-scope": true, + "eslint-plugin-mocha>eslint-utils": true, "eslint>eslint-scope": true, "eslint>eslint-utils": true, "webpack>eslint-scope": true @@ -2630,6 +2771,11 @@ "eslint-plugin-jsdoc>spdx-expression-parse>spdx-license-ids": true } }, + "eslint-plugin-mocha>eslint-utils": { + "packages": { + "eslint-plugin-mocha>eslint-utils>eslint-visitor-keys": true + } + }, "eslint-plugin-node": { "builtin": { "fs.readFileSync": true, @@ -2658,8 +2804,8 @@ }, "eslint-plugin-node>eslint-plugin-es": { "packages": { - "eslint-plugin-node>eslint-plugin-es>eslint-utils": true, - "eslint>regexpp": true + "@typescript-eslint/eslint-plugin>regexpp": true, + "eslint-plugin-node>eslint-plugin-es>eslint-utils": true } }, "eslint-plugin-node>eslint-plugin-es>eslint-utils": { @@ -2819,6 +2965,11 @@ "process": true } }, + "eslint>@eslint-community/eslint-utils": { + "packages": { + "eslint>eslint-visitor-keys": true + } + }, "eslint>@eslint/eslintrc": { "builtin": { "assert": true, @@ -2866,6 +3017,48 @@ "nock>debug": true } }, + "eslint>@nodelib/fs.walk": { + "builtin": { + "events.EventEmitter": true, + "path.sep": true, + "stream.Readable": true + }, + "globals": { + "setImmediate": true + }, + "packages": { + "eslint>@nodelib/fs.walk>@nodelib/fs.scandir": true, + "eslint>@nodelib/fs.walk>fastq": true + } + }, + "eslint>@nodelib/fs.walk>@nodelib/fs.scandir": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.readdir": true, + "fs.readdirSync": true, + "fs.stat": true, + "fs.statSync": true, + "path.sep": true + }, + "globals": { + "process.versions.node": true + }, + "packages": { + "eslint>@nodelib/fs.walk>@nodelib/fs.scandir>run-parallel": true, + "fast-glob>@nodelib/fs.stat": true + } + }, + "eslint>@nodelib/fs.walk>@nodelib/fs.scandir>run-parallel": { + "globals": { + "process.nextTick": true + } + }, + "eslint>@nodelib/fs.walk>fastq": { + "packages": { + "eslint>@nodelib/fs.walk>fastq>reusify": true + } + }, "eslint>ajv": { "globals": { "console": true @@ -2904,11 +3097,6 @@ "eslint-plugin-react>estraverse": true } }, - "eslint>eslint-utils": { - "packages": { - "eslint>eslint-utils>eslint-visitor-keys": true - } - }, "eslint>espree": { "packages": { "eslint>eslint-visitor-keys": true, @@ -2996,6 +3184,13 @@ "eslint>is-glob>is-extglob": true } }, + "eslint>is-path-inside": { + "builtin": { + "path.relative": true, + "path.resolve": true, + "path.sep": true + } + }, "eslint>levn": { "packages": { "eslint>levn>prelude-ls": true, @@ -3074,9 +3269,9 @@ "process.cwd": true }, "packages": { + "eslint>@nodelib/fs.walk": true, + "eslint>glob-parent": true, "fast-glob>@nodelib/fs.stat": true, - "fast-glob>@nodelib/fs.walk": true, - "fast-glob>glob-parent": true, "globby>merge2": true, "stylelint>micromatch": true } @@ -3089,57 +3284,6 @@ "fs.statSync": true } }, - "fast-glob>@nodelib/fs.walk": { - "builtin": { - "events.EventEmitter": true, - "path.sep": true, - "stream.Readable": true - }, - "globals": { - "setImmediate": true - }, - "packages": { - "fast-glob>@nodelib/fs.walk>@nodelib/fs.scandir": true, - "fast-glob>@nodelib/fs.walk>fastq": true - } - }, - "fast-glob>@nodelib/fs.walk>@nodelib/fs.scandir": { - "builtin": { - "fs.lstat": true, - "fs.lstatSync": true, - "fs.readdir": true, - "fs.readdirSync": true, - "fs.stat": true, - "fs.statSync": true, - "path.sep": true - }, - "globals": { - "process.versions.node.split": true - }, - "packages": { - "fast-glob>@nodelib/fs.stat": true, - "fast-glob>@nodelib/fs.walk>@nodelib/fs.scandir>run-parallel": true - } - }, - "fast-glob>@nodelib/fs.walk>@nodelib/fs.scandir>run-parallel": { - "globals": { - "process.nextTick": true - } - }, - "fast-glob>@nodelib/fs.walk>fastq": { - "packages": { - "fast-glob>@nodelib/fs.walk>fastq>reusify": true - } - }, - "fast-glob>glob-parent": { - "builtin": { - "os.platform": true, - "path.posix.dirname": true - }, - "packages": { - "eslint>is-glob": true - } - }, "fs-extra": { "builtin": { "assert": true, @@ -3272,9 +3416,9 @@ "setImmediate": true }, "packages": { + "addons-linter>postcss": true, "fancy-log": true, "gulp-autoprefixer>autoprefixer": true, - "gulp-autoprefixer>postcss": true, "gulp-zip>plugin-error": true, "through2": true, "vinyl-sourcemaps-apply": true @@ -3287,9 +3431,9 @@ "process.env.AUTOPREFIXER_GRID": true }, "packages": { - "addons-linter>postcss>picocolors": true, + "addons-linter>postcss": true, "gulp-autoprefixer>autoprefixer>fraction.js": true, - "gulp-autoprefixer>postcss": true, + "gulp-sass>picocolors": true, "stylelint>autoprefixer>normalize-range": true, "stylelint>postcss-value-parser": true, "webpack>browserslist": true, @@ -3301,110 +3445,6 @@ "define": true } }, - "gulp-autoprefixer>postcss": { - "builtin": { - "fs.existsSync": true, - "fs.readFileSync": true, - "path.dirname": true, - "path.isAbsolute": true, - "path.join": true, - "path.relative": true, - "path.resolve": true, - "path.sep": true, - "url.fileURLToPath": true, - "url.pathToFileURL": true - }, - "globals": { - "Buffer": true, - "URL": true, - "atob": true, - "btoa": true, - "console": true, - "process.env.LANG": true, - "process.env.NODE_ENV": true - }, - "packages": { - "addons-linter>postcss>picocolors": true, - "addons-linter>postcss>source-map-js": true, - "gulp-autoprefixer>postcss>nanoid": true - } - }, - "gulp-dart-sass": { - "builtin": { - "path.basename": true, - "path.dirname": true, - "path.extname": true, - "path.join": true, - "path.relative": true - }, - "globals": { - "process.cwd": true, - "process.stderr.write": true - }, - "packages": { - "gulp-dart-sass>chalk": true, - "gulp-dart-sass>lodash.clonedeep": true, - "gulp-dart-sass>strip-ansi": true, - "gulp-dart-sass>through2": true, - "gulp-zip>plugin-error": true, - "sass": true, - "vinyl-sourcemaps-apply": true, - "vinyl>replace-ext": true - } - }, - "gulp-dart-sass>chalk": { - "globals": { - "process.env.TERM": true, - "process.platform": true - }, - "packages": { - "gulp-dart-sass>chalk>ansi-styles": true, - "gulp-dart-sass>chalk>escape-string-regexp": true, - "gulp-dart-sass>chalk>supports-color": true - } - }, - "gulp-dart-sass>chalk>ansi-styles": { - "packages": { - "@metamask/jazzicon>color>color-convert": true - } - }, - "gulp-dart-sass>chalk>supports-color": { - "builtin": { - "os.release": true - }, - "globals": { - "process.env": true, - "process.platform": true, - "process.stderr": true, - "process.stdout": true, - "process.versions.node.split": true - }, - "packages": { - "gulp-dart-sass>chalk>supports-color>has-flag": true - } - }, - "gulp-dart-sass>chalk>supports-color>has-flag": { - "globals": { - "process.argv": true - } - }, - "gulp-dart-sass>strip-ansi": { - "packages": { - "gulp-dart-sass>strip-ansi>ansi-regex": true - } - }, - "gulp-dart-sass>through2": { - "builtin": { - "util.inherits": true - }, - "globals": { - "process.nextTick": true - }, - "packages": { - "readable-stream": true, - "watchify>xtend": true - } - }, "gulp-livereload": { "builtin": { "path.relative": true @@ -3424,8 +3464,8 @@ "process.platform": true }, "packages": { - "gulp-dart-sass>chalk>escape-string-regexp": true, "gulp-livereload>chalk>ansi-styles": true, + "gulp-livereload>chalk>escape-string-regexp": true, "gulp-livereload>chalk>supports-color": true } }, @@ -3698,7 +3738,7 @@ "process.platform": true }, "packages": { - "gulp-dart-sass>chalk>escape-string-regexp": true, + "gulp-livereload>chalk>escape-string-regexp": true, "gulp-rtlcss>rtlcss>chalk>ansi-styles": true, "gulp-rtlcss>rtlcss>chalk>supports-color": true } @@ -3757,6 +3797,48 @@ "watchify>xtend": true } }, + "gulp-sass": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.relative": true, + "stream.Transform": true + }, + "globals": { + "process.cwd": true, + "process.exit": true, + "process.stderr.write": true + }, + "packages": { + "eslint>strip-ansi": true, + "gulp-sass>lodash.clonedeep": true, + "gulp-sass>picocolors": true, + "gulp-sass>replace-ext": true, + "gulp-zip>plugin-error": true, + "vinyl-sourcemaps-apply": true + } + }, + "gulp-sass>picocolors": { + "builtin": { + "tty.isatty": true + }, + "globals": { + "process.argv.includes": true, + "process.env": true, + "process.platform": true + } + }, + "gulp-sass>replace-ext": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.sep": true + } + }, "gulp-sort": { "packages": { "gulp-sort>through2": true @@ -4073,11 +4155,11 @@ "setTimeout": true }, "packages": { + "eslint>glob-parent": true, "gulp-watch>ansi-colors": true, "gulp-watch>anymatch": true, "gulp-watch>chokidar": true, "gulp-watch>fancy-log": true, - "gulp-watch>glob-parent": true, "gulp-watch>path-is-absolute": true, "gulp-watch>slash": true, "gulp-watch>vinyl-file": true, @@ -4168,8 +4250,8 @@ "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic": { "packages": { "@babel/register>clone-deep>kind-of": true, - "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>math-random": true, - "gulp>undertaker>bach>array-last>is-number": true + "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>is-number": true, + "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>math-random": true } }, "gulp-watch>anymatch>micromatch>braces>expand-range>fill-range>randomatic>math-random": { @@ -4221,15 +4303,7 @@ "path.dirname": true }, "packages": { - "gulp-watch>anymatch>micromatch>parse-glob>glob-base>glob-parent": true, - "gulp-watch>anymatch>micromatch>parse-glob>glob-base>is-glob": true - } - }, - "gulp-watch>anymatch>micromatch>parse-glob>glob-base>glob-parent": { - "builtin": { - "path.dirname": true - }, - "packages": { + "eslint>glob-parent": true, "gulp-watch>anymatch>micromatch>parse-glob>glob-base>is-glob": true } }, @@ -4282,6 +4356,7 @@ }, "packages": { "chokidar>normalize-path": true, + "eslint>glob-parent": true, "eslint>is-glob": true, "gulp-watch>chokidar>anymatch": true, "gulp-watch>chokidar>async-each": true, @@ -4457,20 +4532,10 @@ }, "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values": { "packages": { - "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>is-number": true, + "gulp-watch>chokidar>braces>fill-range>is-number": true, "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>kind-of": true } }, - "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>is-number": { - "packages": { - "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>is-number>kind-of": true - } - }, - "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>is-number>kind-of": { - "packages": { - "browserify>insert-module-globals>is-buffer": true - } - }, "gulp-watch>chokidar>braces>snapdragon>base>cache-base>has-value>has-values>kind-of": { "packages": { "browserify>insert-module-globals>is-buffer": true @@ -4885,30 +4950,6 @@ "fancy-log>time-stamp": true } }, - "gulp-watch>glob-parent": { - "builtin": { - "os.platform": true, - "path": true - }, - "packages": { - "gulp-watch>glob-parent>is-glob": true, - "gulp-watch>glob-parent>path-dirname": true - } - }, - "gulp-watch>glob-parent>is-glob": { - "packages": { - "gulp-watch>glob-parent>is-glob>is-extglob": true - } - }, - "gulp-watch>glob-parent>path-dirname": { - "builtin": { - "path": true, - "util.inspect": true - }, - "globals": { - "process.platform": true - } - }, "gulp-watch>path-is-absolute": { "globals": { "process.platform": true @@ -5206,9 +5247,9 @@ }, "packages": { "chokidar>normalize-path": true, + "eslint>glob-parent": true, "eslint>is-glob": true, "gulp-watch>chokidar>async-each": true, - "gulp-watch>glob-parent": true, "gulp-watch>path-is-absolute": true, "gulp>glob-watcher>anymatch": true, "gulp>glob-watcher>chokidar>braces": true, @@ -5239,24 +5280,14 @@ }, "packages": { "gulp-watch>chokidar>braces>extend-shallow": true, - "gulp>glob-watcher>chokidar>braces>fill-range>is-number": true, + "gulp-watch>chokidar>braces>fill-range>is-number": true, "gulp>glob-watcher>chokidar>braces>fill-range>to-regex-range": true, "stylelint>@stylelint/postcss-markdown>remark>remark-parse>repeat-string": true } }, - "gulp>glob-watcher>chokidar>braces>fill-range>is-number": { - "packages": { - "gulp>glob-watcher>chokidar>braces>fill-range>is-number>kind-of": true - } - }, - "gulp>glob-watcher>chokidar>braces>fill-range>is-number>kind-of": { - "packages": { - "browserify>insert-module-globals>is-buffer": true - } - }, "gulp>glob-watcher>chokidar>braces>fill-range>to-regex-range": { "packages": { - "gulp>glob-watcher>chokidar>braces>fill-range>is-number": true, + "gulp-watch>chokidar>braces>fill-range>is-number": true, "stylelint>@stylelint/postcss-markdown>remark>remark-parse>repeat-string": true } }, @@ -5406,7 +5437,6 @@ "gulp>gulp-cli>matchdep>micromatch>fragment-cache": true, "gulp>gulp-cli>matchdep>micromatch>nanomatch>define-property": true, "gulp>gulp-cli>matchdep>micromatch>nanomatch>extend-shallow": true, - "gulp>gulp-cli>matchdep>micromatch>nanomatch>is-odd": true, "gulp>gulp-cli>matchdep>micromatch>regex-not": true, "nyc>spawn-wrap>is-windows": true } @@ -5428,11 +5458,6 @@ "@babel/register>clone-deep>is-plain-object": true } }, - "gulp>gulp-cli>matchdep>micromatch>nanomatch>is-odd": { - "packages": { - "gulp>undertaker>bach>array-last>is-number": true - } - }, "gulp>gulp-cli>matchdep>micromatch>regex-not": { "packages": { "gulp-watch>chokidar>braces>to-regex>safe-regex": true, @@ -5522,7 +5547,7 @@ }, "gulp>undertaker>bach>array-initial": { "packages": { - "gulp>undertaker>bach>array-last>is-number": true, + "gulp>undertaker>bach>array-initial>is-number": true, "gulp>undertaker>object.defaults>array-slice": true } }, @@ -5652,7 +5677,7 @@ "process.nextTick": true }, "packages": { - "gulp-watch>glob-parent": true, + "eslint>glob-parent": true, "gulp>glob-watcher>is-negated-glob": true, "gulp>vinyl-fs>glob-stream>ordered-read-streams": true, "gulp>vinyl-fs>glob-stream>pumpify": true, @@ -6066,7 +6091,7 @@ "process.platform": true }, "packages": { - "gulp-dart-sass>chalk>escape-string-regexp": true, + "gulp-livereload>chalk>escape-string-regexp": true, "lavamoat>@babel/highlight>chalk>ansi-styles": true, "lavamoat>@babel/highlight>chalk>supports-color": true } @@ -6251,6 +6276,38 @@ "process.platform": true } }, + "mocha>find-up": { + "builtin": { + "path.dirname": true, + "path.parse": true, + "path.resolve": true + }, + "packages": { + "mocha>find-up>locate-path": true, + "nyc>find-up>path-exists": true + } + }, + "mocha>find-up>locate-path": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.stat": true, + "fs.statSync": true, + "path.resolve": true, + "util.promisify": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "mocha>find-up>locate-path>p-locate": true + } + }, + "mocha>find-up>locate-path>p-locate": { + "packages": { + "copy-webpack-plugin>p-limit": true + } + }, "mocha>log-symbols": { "packages": { "madge>ora>is-unicode-supported": true, @@ -6358,6 +6415,13 @@ "Buffer.from": true } }, + "nyc>find-up>path-exists": { + "builtin": { + "fs.access": true, + "fs.accessSync": true, + "util.promisify": true + } + }, "nyc>glob": { "builtin": { "assert": true, @@ -6688,6 +6752,7 @@ "url.resolve": true }, "globals": { + "TextDecoder": true, "setImmediate": true }, "packages": { @@ -7306,7 +7371,7 @@ }, "stylelint>postcss-html>htmlparser2>domutils>dom-serializer": { "packages": { - "stylelint>postcss-html>htmlparser2>domelementtype": true, + "stylelint>postcss-html>htmlparser2>domutils>dom-serializer>domelementtype": true, "stylelint>postcss-html>htmlparser2>entities": true } }, @@ -7610,7 +7675,7 @@ }, "terser": { "globals": { - "Buffer.from": true, + "Buffer": true, "atob": true, "btoa": true, "console.log": true, diff --git a/package.json b/package.json index 365642414..ab1a1ccb8 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ }, "scripts": { "start": "yarn build:dev dev --apply-lavamoat=false --snow=false", - "start:lavamoat": "yarn build:dev dev --apply-lavamoat=true", "start:mv3": "ENABLE_MV3=true yarn build:dev dev --apply-lavamoat=false", "start:flask": "yarn start --build-type flask", + "start:lavamoat": "yarn build:dev dev --apply-lavamoat=true", "dist": "yarn build dist", "build": "yarn lavamoat:build", "build:dev": "node development/build/index.js", "start:test": "SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' SENTRY_DSN_DEV=https://fake@sentry.io/0000000 PORTFOLIO_URL=http://127.0.0.1:8080 yarn build:dev testDev", + "start:test:mv3": "ENABLE_MV3=true SEGMENT_HOST='https://api.segment.io' SEGMENT_WRITE_KEY='FAKE' SENTRY_DSN_DEV=https://fake@sentry.io/0000000 PORTFOLIO_URL=http://127.0.0.1:8080 yarn build:dev testDev", "benchmark:chrome": "SELENIUM_BROWSER=chrome ts-node test/e2e/benchmark.js", "mv3:stats:chrome": "SELENIUM_BROWSER=chrome ENABLE_MV3=true ts-node test/e2e/mv3-perf-stats/index.js", "user-actions-benchmark:chrome": "SELENIUM_BROWSER=chrome ts-node test/e2e/user-actions-benchmark.js", @@ -91,15 +92,18 @@ "test-storybook": "test-storybook -c .storybook", "test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"yarn storybook:build && npx http-server storybook-build --port 6006 \" \"wait-on tcp:6006 && yarn test-storybook --maxWorkers=2\"", "githooks:install": "husky install", - "fitness-functions": "node development/fitness-functions/index.js", + "fitness-functions": "ts-node development/fitness-functions/index.ts", "generate-beta-commit": "node ./development/generate-beta-commit.js" }, "resolutions": { "analytics-node/axios": "^0.21.2", "ganache-core/lodash": "^4.17.21", + "git-url-parse@^12.0.0": "^13.1.0", + "glob-parent": "^6.0.2", "netmask": "^2.0.1", "json-schema": "^0.4.0", "ast-types": "^0.14.2", + "x-default-browser": "^0.5.2", "web3-provider-engine/eth-json-rpc-filters": "^6.0.0", "typescript@~4.4.0": "patch:typescript@npm:4.4.4#.yarn/patches/typescript-npm-4.4.4-3fedcc07a3.patch", "acorn@^7.0.0": "patch:acorn@npm:7.4.1#.yarn/patches/acorn-npm-7.4.1-f450b4646c.patch", @@ -128,8 +132,8 @@ "abort-controller@^3.0.0": "patch:abort-controller@npm%3A3.0.0#./.yarn/patches/abort-controller-npm-3.0.0-2f3a9a2bcb.patch", "await-semaphore@^0.1.1": "patch:await-semaphore@npm%3A0.1.3#./.yarn/patches/await-semaphore-npm-0.1.3-b7a0001fab.patch", "await-semaphore@^0.1.3": "patch:await-semaphore@npm%3A0.1.3#./.yarn/patches/await-semaphore-npm-0.1.3-b7a0001fab.patch", - "eslint@^8.20.0": "patch:eslint@npm%3A8.20.0#./.yarn/patches/eslint-npm-8.20.0-6bbc377ff7.patch", - "eslint@8.14.0": "patch:eslint@npm%3A8.20.0#./.yarn/patches/eslint-npm-8.20.0-6bbc377ff7.patch", + "eslint@8.36.0": "patch:eslint@npm%3A8.36.0#./.yarn/patches/eslint-npm-8.36.0-f8482bce95.patch", + "eslint@^8.36.0": "patch:eslint@npm%3A8.36.0#./.yarn/patches/eslint-npm-8.36.0-f8482bce95.patch", "eth-query@^2.1.2": "patch:eth-query@npm%3A2.1.2#./.yarn/patches/eth-query-npm-2.1.2-7c6adc825f.patch", "eth-query@^2.1.0": "patch:eth-query@npm%3A2.1.2#./.yarn/patches/eth-query-npm-2.1.2-7c6adc825f.patch", "ethereumjs-util@^5.1.1": "patch:ethereumjs-util@npm%3A5.2.1#./.yarn/patches/ethereumjs-util-npm-5.2.1-72b39f4e7e.patch", @@ -175,7 +179,7 @@ "@babel/runtime@^7.12.5": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch", "@babel/runtime@^7.5.0": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch", "@babel/runtime@^7.8.4": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch", - "@eslint/eslintrc@^1.3.0": "patch:@eslint/eslintrc@npm%3A1.3.0#./.yarn/patches/@eslint-eslintrc-npm-1.3.0-1f3c51be25.patch", + "@eslint/eslintrc@^2.0.1": "patch:@eslint/eslintrc@npm%3A2.0.2#./.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch", "@formatjs/intl-utils@^3.3.1": "patch:@formatjs/intl-utils@npm%3A3.3.1#./.yarn/patches/@formatjs-intl-utils-npm-3.3.1-08510c16ad.patch", "@fortawesome/fontawesome-free@^5.13.0": "patch:@fortawesome/fontawesome-free@npm%3A5.13.0#./.yarn/patches/@fortawesome-fontawesome-free-npm-5.13.0-f20fc0388d.patch", "@keystonehq/bc-ur-registry@^0.5.0-alpha.5": "patch:@keystonehq/bc-ur-registry@npm%3A0.5.0-alpha.5#./.yarn/patches/@keystonehq-bc-ur-registry-npm-0.5.0-alpha.5-b95c7992a6.patch", @@ -226,10 +230,10 @@ "@metamask/address-book-controller": "^2.0.0", "@metamask/announcement-controller": "^3.0.0", "@metamask/approval-controller": "^2.1.0", - "@metamask/assets-controllers": "^5.0.0", + "@metamask/assets-controllers": "^6.0.0", "@metamask/base-controller": "^2.0.0", "@metamask/contract-metadata": "^2.3.1", - "@metamask/controller-utils": "^3.1.0", + "@metamask/controller-utils": "^3.3.0", "@metamask/design-tokens": "^1.9.0", "@metamask/desktop": "^0.3.0", "@metamask/eth-json-rpc-infura": "^8.0.0", @@ -243,7 +247,7 @@ "@metamask/jazzicon": "^2.0.0", "@metamask/key-tree": "^7.0.0", "@metamask/logo": "^3.1.1", - "@metamask/message-manager": "^3.0.0", + "@metamask/message-manager": "^3.1.1", "@metamask/metamask-eth-abis": "^3.0.0", "@metamask/notification-controller": "^2.0.0", "@metamask/obs-store": "^8.1.0", @@ -253,13 +257,17 @@ "@metamask/providers": "^10.2.1", "@metamask/rate-limit-controller": "^2.0.0", "@metamask/rpc-methods": "^0.32.2", + "@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.32.2", "@metamask/safe-event-emitter": "^2.0.0", "@metamask/scure-bip39": "^2.0.3", - "@metamask/slip44": "^2.1.0", + "@metamask/slip44": "^3.0.0", "@metamask/smart-transactions-controller": "^3.1.0", "@metamask/snaps-controllers": "^0.32.2", + "@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.32.2", "@metamask/snaps-ui": "^0.32.2", + "@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.32.2", "@metamask/snaps-utils": "^0.32.2", + "@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.32.2", "@metamask/subject-metadata-controller": "^2.0.0", "@metamask/swappable-obj-proxy": "^2.1.0", "@metamask/utils": "^5.0.0", @@ -346,7 +354,7 @@ "redux-thunk": "^2.3.0", "remove-trailing-slash": "^0.1.1", "reselect": "^3.0.1", - "ses": "^0.12.4", + "ses": "^0.18.4", "single-call-balance-checker-abi": "^1.0.0", "unicode-confusables": "^0.1.1", "uuid": "^8.3.2", @@ -375,7 +383,7 @@ "@metamask/eslint-config-typescript": "^9.0.1", "@metamask/forwarder": "^1.1.0", "@metamask/phishing-warning": "^2.1.0", - "@metamask/test-dapp": "^5.6.0", + "@metamask/test-dapp": "^6.0.0", "@sentry/cli": "^1.58.0", "@storybook/addon-a11y": "^6.5.13", "@storybook/addon-actions": "^6.5.13", @@ -405,7 +413,7 @@ "@types/fs-extra": "^9.0.13", "@types/gulp": "^4.0.9", "@types/gulp-autoprefixer": "^0.0.33", - "@types/gulp-dart-sass": "^1.0.1", + "@types/gulp-sass": "^5.0.0", "@types/gulp-sourcemaps": "^0.0.35", "@types/jest": "^29.1.2", "@types/jest-when": "^3.5.2", @@ -417,6 +425,7 @@ "@types/react-dom": "^17.0.11", "@types/react-redux": "^7.1.25", "@types/remote-redux-devtools": "^0.5.5", + "@types/sass": "^1.43.1", "@types/sinon": "^10.0.13", "@types/w3c-web-hid": "^1.0.3", "@types/watchify": "^3.11.1", @@ -425,6 +434,7 @@ "@typescript-eslint/parser": "^5.30.7", "@whitespace/storybook-addon-html": "^5.1.1", "addons-linter": "^5.2.0", + "babel-plugin-module-resolver": "^5.0.0", "babelify": "^10.0.0", "bify-module-groups": "^2.0.0", "brfs": "^2.0.2", @@ -443,7 +453,7 @@ "depcheck": "^1.4.3", "dependency-tree": "^8.1.2", "duplexify": "^4.1.1", - "eslint": "^8.20.0", + "eslint": "^8.36.0", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-node": "^0.3.4", "eslint-import-resolver-typescript": "^2.5.0", @@ -465,10 +475,10 @@ "globby": "^11.0.4", "gulp": "^4.0.2", "gulp-autoprefixer": "^8.0.0", - "gulp-dart-sass": "^1.0.2", "gulp-livereload": "4.0.0", "gulp-rename": "^2.0.0", "gulp-rtlcss": "^1.4.0", + "gulp-sass": "^5.1.0", "gulp-sort": "^2.0.0", "gulp-sourcemaps": "^3.0.0", "gulp-stylelint": "^13.0.0", @@ -516,7 +526,7 @@ "resolve-url-loader": "^3.1.5", "sass": "^1.32.4", "sass-loader": "^10.1.1", - "selenium-webdriver": "^4.3.1", + "selenium-webdriver": "^4.9.0", "semver": "^7.3.5", "serve-handler": "^6.1.2", "sinon": "^9.0.0", @@ -528,6 +538,7 @@ "string.prototype.matchall": "^4.0.2", "style-loader": "^0.21.0", "stylelint": "^13.6.1", + "superstruct": "^1.0.3", "terser": "^5.7.0", "through2": "^4.0.2", "ts-node": "^10.5.0", diff --git a/shared/constants/app.ts b/shared/constants/app.ts index c8be0573e..3b99fa5e7 100644 --- a/shared/constants/app.ts +++ b/shared/constants/app.ts @@ -1,4 +1,4 @@ -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import { DialogType } from '@metamask/rpc-methods'; ///: END:ONLY_INCLUDE_IN import { RestrictedMethods } from './permissions'; @@ -20,18 +20,6 @@ export const ENVIRONMENT_TYPE_NOTIFICATION = 'notification'; export const ENVIRONMENT_TYPE_FULLSCREEN = 'fullscreen'; export const ENVIRONMENT_TYPE_BACKGROUND = 'background'; -/** - * The distribution this build is intended for. - * - * This should be kept in-sync with the `BuildType` map in `development/build/utils.js`. - */ -export const BuildType = { - beta: 'beta', - desktop: 'desktop', - flask: 'flask', - main: 'main', -} as const; - export const PLATFORM_BRAVE = 'Brave'; export const PLATFORM_CHROME = 'Chrome'; export const PLATFORM_EDGE = 'Edge'; @@ -57,12 +45,12 @@ export const MESSAGE_TYPE = { WALLET_REQUEST_PERMISSIONS: 'wallet_requestPermissions', WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET_LEGACY: 'metamask_watchAsset', - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) SNAP_DIALOG_ALERT: `${RestrictedMethods.snap_dialog}:alert`, SNAP_DIALOG_CONFIRMATION: `${RestrictedMethods.snap_dialog}:confirmation`, SNAP_DIALOG_PROMPT: `${RestrictedMethods.snap_dialog}:prompt`, ///: END:ONLY_INCLUDE_IN - ///: BEGIN:ONLY_INCLUDE_IN(mmi) + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) MMI_AUTHENTICATE: 'metamaskinstitutional_authenticate', MMI_REAUTHENTICATE: 'metamaskinstitutional_reauthenticate', MMI_REFRESH_TOKEN: 'metamaskinstitutional_refresh_token', @@ -75,7 +63,7 @@ export const MESSAGE_TYPE = { ///: END:ONLY_INCLUDE_IN } as const; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) export const SNAP_DIALOG_TYPES = { [DialogType.Alert]: MESSAGE_TYPE.SNAP_DIALOG_ALERT, [DialogType.Confirmation]: MESSAGE_TYPE.SNAP_DIALOG_CONFIRMATION, diff --git a/shared/constants/environment.js b/shared/constants/environment.js deleted file mode 100644 index ffc551ccd..000000000 --- a/shared/constants/environment.js +++ /dev/null @@ -1,2 +0,0 @@ -export const isMain = process.env.METAMASK_BUILD_TYPE === 'main'; -export const isFlask = process.env.METAMASK_BUILD_TYPE === 'flask'; diff --git a/shared/constants/hardware-wallets.ts b/shared/constants/hardware-wallets.ts index 4f549aa2f..9f5d6ba89 100644 --- a/shared/constants/hardware-wallets.ts +++ b/shared/constants/hardware-wallets.ts @@ -33,7 +33,7 @@ export enum HardwareAffiliateLinks { ledger = 'https://shop.ledger.com/?r=17c4991a03fa', gridplus = 'https://gridplus.io/?afmc=7p', trezor = 'https://shop.trezor.io/product/trezor-one-black?offer_id=35&aff_id=11009', - keystone = 'https://shop.keyst.one/?rfsn=6088257.656b3e9&utm_source=refersion&utm_medium=affiliate&utm_campaign=6088257.656b3e9', + keystone = 'https://keyst.one/metamask?rfsn=6088257.656b3e9&utm_source=refersion&utm_medium=affiliate&utm_campaign=6088257.656b3e9', airgap = 'https://airgap.it/', coolwallet = 'https://www.coolwallet.io/', dcent = 'https://dcentwallet.com/', diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 44647668b..5e970ca0b 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -358,6 +358,20 @@ export type MetaMetricsUserTraits = { * Whether the security provider feature has been enabled. */ security_providers?: string[]; + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + /** + * The address of the MMI account in question + */ + mmi_account_address?: string; + /** + * What is the MMI extension ID + */ + mmi_extension_id?: string; + /** + * Is the user using a custodian account + */ + mmi_is_custodian?: boolean; + ///: END:ONLY_INCLUDE_IN }; export enum MetaMetricsUserTrait { @@ -427,6 +441,20 @@ export enum MetaMetricsUserTrait { * Identified when the security provider feature is enabled. */ SecurityProviders = 'security_providers', + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + /** + * Identified when we get the current account in question + */ + MmiAccountAddress = 'mmi_account_address', + /** + * Identified when we the user has the extension + */ + MmiExtensionId = 'mmi_extension_id', + /** + * Identified when the user connects a custodian + */ + MmiIsCustodian = 'mmi_is_custodian', + ///: END:ONLY_INCLUDE_IN } /** @@ -455,9 +483,11 @@ export enum MetaMetricsEventName { AccountAddFailed = 'Account Add Failed', AccountPasswordCreated = 'Account Password Created', AccountReset = 'Account Reset', + AccountRenamed = 'Account Renamed', AppInstalled = 'App Installed', AppUnlocked = 'App Unlocked', AppUnlockedFailed = 'App Unlocked Failed', + AppLocked = 'App Locked', AppWindowExpanded = 'App Window Expanded', BridgeLinkClicked = 'Bridge Link Clicked', DecryptionApproved = 'Decryption Approved', @@ -492,34 +522,7 @@ export enum MetaMetricsEventName { NavBuyButtonClicked = 'Buy Button Clicked', NavSendButtonClicked = 'Send Button Clicked', NavSwapButtonClicked = 'Swap Button Clicked', - SrpToConfirmBackup = 'SRP Backup Confirm Displayed', - WalletSetupStarted = 'Wallet Setup Selected', - WalletSetupCanceled = 'Wallet Setup Canceled', - WalletSetupFailed = 'Wallet Setup Failed', - WalletCreated = 'Wallet Created', NftAdded = 'NFT Added', - OnrampProviderSelected = 'On-ramp Provider Selected', - PermissionsApproved = 'Permissions Approved', - PermissionsRejected = 'Permissions Rejected', - PermissionsRequested = 'Permissions Requested', - PhishingPageDisplayed = 'Phishing Page Displayed', - PortfolioLinkClicked = 'Portfolio Link Clicked', - PublicAddressCopied = 'Public Address Copied', - ProviderMethodCalled = 'Provider Method Called', - SignatureApproved = 'Signature Approved', - SignatureFailed = 'Signature Failed', - SignatureRejected = 'Signature Rejected', - SignatureRequested = 'Signature Requested', - TermsOfUseShown = 'Terms of Use Shown', - TermsOfUseAccepted = 'Terms of Use Accepted', - TokenImportButtonClicked = 'Import Token Button Clicked', - TokenScreenOpened = 'Token Screen Opened', - SupportLinkClicked = 'Support Link Clicked', - TokenAdded = 'Token Added', - TokenDetected = 'Token Detected', - TokenHidden = 'Token Hidden', - TokenImportCanceled = 'Token Import Canceled', - TokenImportClicked = 'Token Import Clicked', OnboardingWelcome = 'App Installed', OnboardingWalletCreationStarted = 'Wallet Setup Selected', OnboardingWalletImportStarted = 'Wallet Import Started', @@ -537,13 +540,68 @@ export enum MetaMetricsEventName { OnboardingWalletImportAttempted = 'Wallet Import Attempted', OnboardingWalletVideoPlay = 'SRP Intro Video Played', OnboardingTwitterClick = 'External Link Clicked', + OnrampProviderSelected = 'On-ramp Provider Selected', + PermissionsApproved = 'Permissions Approved', + PermissionsRejected = 'Permissions Rejected', + PermissionsRequested = 'Permissions Requested', + PhishingPageDisplayed = 'Phishing Page Displayed', + PortfolioLinkClicked = 'Portfolio Link Clicked', + ProviderMethodCalled = 'Provider Method Called', + PublicAddressCopied = 'Public Address Copied', ServiceWorkerRestarted = 'Service Worker Restarted', + SignatureApproved = 'Signature Approved', + SignatureFailed = 'Signature Failed', + SignatureRejected = 'Signature Rejected', + SignatureRequested = 'Signature Requested', + SrpRevealStarted = 'Reveal SRP Initiated', + SrpRevealClicked = 'Clicked Reveal Secret Recovery', + SrpRevealViewed = 'Views Reveal Secret Recovery', + SrpRevealBackButtonClicked = 'Clicked Back on Reveal SRP Password Page', + SrpRevealCancelled = 'Reveal SRP Cancelled', + SrpRevealCancelButtonClicked = 'Clicks Cancel on Reveal Secret Recovery Phrase Page', + SrpRevealCloseClicked = 'Clicks CLOSE with SRP', + SrpRevealNextClicked = 'Clicks Next on Reveal Secret Recovery Phrase', + SrpHoldToRevealClickStarted = 'Reveal SRP Click Started', + SrpHoldToRevealCloseClicked = 'Closes Hold To Reveal SRP', + SrpHoldToRevealCompleted = 'Reveal SRP Completed', + SrpViewsSrpQR = 'Views SRP QR Code', + SrpViewSrpText = 'Views SRP', + SrpCopiedToClipboard = 'Copies SRP to clipboard', + SrpToConfirmBackup = 'SRP Backup Confirm Displayed', + SupportLinkClicked = 'Support Link Clicked', + TermsOfUseShown = 'Terms of Use Shown', + TermsOfUseAccepted = 'Terms of Use Accepted', + TokenImportButtonClicked = 'Import Token Button Clicked', + TokenScreenOpened = 'Token Screen Opened', + TokenAdded = 'Token Added', + TokenDetected = 'Token Detected', + TokenHidden = 'Token Hidden', + TokenImportCanceled = 'Token Import Canceled', + TokenImportClicked = 'Token Import Clicked', + WalletSetupStarted = 'Wallet Setup Selected', + WalletSetupCanceled = 'Wallet Setup Canceled', + WalletSetupFailed = 'Wallet Setup Failed', + WalletCreated = 'Wallet Created', + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + UserClickedDeepLink = 'User clicked deeplink', + ///: END:ONLY_INCLUDE_IN + AccountDetailMenuOpened = 'Account Details Menu Opened', + BlockExplorerLinkClicked = 'Block Explorer Clicked', + AccountRemoved = 'Account Removed', + TestNetworksDisplayed = 'Test Networks Displayed', + AddNetworkButtonClick = 'Add Network Button Clicked', + CustomNetworkAdded = 'Custom Network Added', + TokenDetailsOpened = 'Token Details Opened', + NftScreenOpened = 'NFT Screen Opened', + ActivityScreenOpened = 'Activity Screen Opened', + WhatsNewViewed = `What's New Viewed`, + WhatsNewClicked = `What's New Link Clicked`, } export enum MetaMetricsEventAccountType { Default = 'metamask', - Imported = 'imported', Hardware = 'hardware', + Imported = 'imported', } export enum MetaMetricsEventAccountImportType { @@ -557,6 +615,7 @@ export enum MetaMetricsEventCategory { App = 'App', Auth = 'Auth', Background = 'Background', + Desktop = 'Desktop', // The TypeScript ESLint rule is incorrectly marking this line. /* eslint-disable-next-line @typescript-eslint/no-shadow */ Error = 'Error', @@ -570,20 +629,23 @@ export enum MetaMetricsEventCategory { Onboarding = 'Onboarding', Phishing = 'Phishing', Retention = 'Retention', + ServiceWorkers = 'service_workers', Settings = 'Settings', Snaps = 'Snaps', Swaps = 'Swaps', Transactions = 'Transactions', Wallet = 'Wallet', - Desktop = 'Desktop', - ServiceWorkers = 'service_workers', + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + MMI = 'Institutional', + ///: END:ONLY_INCLUDE_IN + Tokens = 'Tokens', } export enum MetaMetricsEventLinkType { - TransactionBlockExplorer = 'Transaction Block Explorer', - BlockExplorer = 'Block Explorer', AccountTracker = 'Account Tracker', + BlockExplorer = 'Block Explorer', TokenTracker = 'Token Tracker', + TransactionBlockExplorer = 'Transaction Block Explorer', } export enum MetaMetricsEventKeyType { @@ -595,9 +657,9 @@ export enum MetaMetricsEventKeyType { export enum MetaMetricsEventOnrampProviderType { Coinbase = 'coinbase', Moonpay = 'moonpay', - Wyre = 'wyre', - Transak = 'transak', SelfDeposit = 'direct_deposit', + Transak = 'transak', + Wyre = 'wyre', } export enum MetaMetricsNetworkEventSource { diff --git a/shared/constants/network.ts b/shared/constants/network.ts index 5227efe2e..bd3bec0fa 100644 --- a/shared/constants/network.ts +++ b/shared/constants/network.ts @@ -540,16 +540,13 @@ export const BUYABLE_CHAINS_MAP: { | typeof CHAIN_IDS.MOONRIVER | typeof CHAIN_IDS.AURORA | typeof CHAIN_IDS.LINEA_TESTNET + | typeof CHAIN_IDS.GOERLI >]: BuyableChainSettings; } = { [CHAIN_IDS.MAINNET]: { nativeCurrency: CURRENCY_SYMBOLS.ETH, network: BUYABLE_CHAIN_ETHEREUM_NETWORK_NAME, }, - [CHAIN_IDS.GOERLI]: { - nativeCurrency: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.GOERLI], - network: BUYABLE_CHAIN_ETHEREUM_NETWORK_NAME, - }, [CHAIN_IDS.SEPOLIA]: { nativeCurrency: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.SEPOLIA], network: BUYABLE_CHAIN_ETHEREUM_NETWORK_NAME, diff --git a/shared/constants/permissions.test.js b/shared/constants/permissions.test.js index aa4f9f489..fb68e5342 100644 --- a/shared/constants/permissions.test.js +++ b/shared/constants/permissions.test.js @@ -9,13 +9,15 @@ import { describe('EndowmentPermissions', () => { it('has the expected permission keys', () => { + // Since long-running is fenced out this causes problems with the test, we re-add it here. expect(Object.keys(EndowmentPermissions).sort()).toStrictEqual( - Object.keys(endowmentPermissionBuilders) - .filter( + [ + 'endowment:long-running', + ...Object.keys(endowmentPermissionBuilders).filter( (targetKey) => !Object.keys(ExcludedSnapEndowments).includes(targetKey), - ) - .sort(), + ), + ].sort(), ); }); }); diff --git a/shared/constants/permissions.ts b/shared/constants/permissions.ts index 4de83b52f..3380327b2 100644 --- a/shared/constants/permissions.ts +++ b/shared/constants/permissions.ts @@ -4,7 +4,7 @@ export const CaveatTypes = Object.freeze({ export const RestrictedMethods = Object.freeze({ eth_accounts: 'eth_accounts', - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) snap_dialog: 'snap_dialog', snap_notify: 'snap_notify', snap_manageState: 'snap_manageState', @@ -16,30 +16,6 @@ export const RestrictedMethods = Object.freeze({ ///: END:ONLY_INCLUDE_IN } as const); -///: BEGIN:ONLY_INCLUDE_IN(flask) -/** - * Exclude permissions by code fencing them to avoid any potential usage of excluded permissions at runtime. See: https://github.com/MetaMask/metamask-extension/pull/17321#pullrequestreview-1287014285. - * This is a fix for https://github.com/MetaMask/snaps-monorepo/issues/1103 and https://github.com/MetaMask/snaps-monorepo/issues/990. - * TODO: Disable endowment:long-running and eth_account in stable. - */ -export const EndowmentPermissions = Object.freeze({ - 'endowment:network-access': 'endowment:network-access', - 'endowment:transaction-insight': 'endowment:transaction-insight', - 'endowment:cronjob': 'endowment:cronjob', - 'endowment:ethereum-provider': 'endowment:ethereum-provider', - 'endowment:rpc': 'endowment:rpc', - 'endowment:long-running': 'endowment:long-running', - 'endowment:webassembly': 'endowment:webassembly', -} as const); - -// Methods / permissions in external packages that we are temporarily excluding. -export const ExcludedSnapPermissions = Object.freeze({ - eth_accounts: - 'eth_accounts is disabled. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/990.', -}); - -export const ExcludedSnapEndowments = Object.freeze({ - 'endowment:keyring': - 'This endowment is still in development therefore not available.', -}); +///: BEGIN:ONLY_INCLUDE_IN(snaps) +export * from './snaps/permissions'; ///: END:ONLY_INCLUDE_IN diff --git a/shared/constants/snaps.ts b/shared/constants/snaps.ts index 6a272cbb8..f3f43e557 100644 --- a/shared/constants/snaps.ts +++ b/shared/constants/snaps.ts @@ -1,4 +1,4 @@ -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import type { SupportedCurve } from '@metamask/key-tree'; type SnapsMetadata = { diff --git a/shared/constants/snaps/permissions.ts b/shared/constants/snaps/permissions.ts new file mode 100644 index 000000000..2a5b3f1f6 --- /dev/null +++ b/shared/constants/snaps/permissions.ts @@ -0,0 +1,26 @@ +export const EndowmentPermissions = Object.freeze({ + 'endowment:network-access': 'endowment:network-access', + 'endowment:transaction-insight': 'endowment:transaction-insight', + 'endowment:cronjob': 'endowment:cronjob', + 'endowment:ethereum-provider': 'endowment:ethereum-provider', + 'endowment:rpc': 'endowment:rpc', + 'endowment:webassembly': 'endowment:webassembly', + ///: BEGIN:ONLY_INCLUDE_IN(build-flask) + 'endowment:long-running': 'endowment:long-running', + ///: END:ONLY_INCLUDE_IN +} as const); + +// Methods / permissions in external packages that we are temporarily excluding. +export const ExcludedSnapPermissions = Object.freeze({ + eth_accounts: + 'eth_accounts is disabled. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/990.', +}); + +export const ExcludedSnapEndowments = Object.freeze({ + 'endowment:keyring': + 'This endowment is still in development therefore not available.', + ///: BEGIN:ONLY_INCLUDE_IN(build-main) + 'endowment:long-running': + 'endowment:long-running is deprecated. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/945.', + ///: END:ONLY_INCLUDE_IN +}); diff --git a/shared/constants/transaction.ts b/shared/constants/transaction.ts index 5e136b814..dad1a72e1 100644 --- a/shared/constants/transaction.ts +++ b/shared/constants/transaction.ts @@ -308,7 +308,7 @@ interface DappSuggestedGasFees { * An object representing a transaction, in whatever state it is in. */ export interface TransactionMeta { - ///: BEGIN:ONLY_INCLUDE_IN(mmi) + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) custodyStatus: string; custodyId?: string; ///: END:ONLY_INCLUDE_IN diff --git a/shared/lib/error-utils.js b/shared/lib/error-utils.js index 631fd04b0..d7a7d284d 100644 --- a/shared/lib/error-utils.js +++ b/shared/lib/error-utils.js @@ -1,4 +1,4 @@ -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(desktop) import browser from 'webextension-polyfill'; ///: END:ONLY_INCLUDE_IN import { memoize } from 'lodash'; @@ -7,7 +7,7 @@ import { fetchLocale, loadRelativeTimeFormatLocaleData, } from '../../ui/helpers/utils/i18n-helper'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(desktop) import { renderDesktopError } from '../../ui/pages/desktop-error/render-desktop-error'; import { EXTENSION_ERROR_PAGE_TYPES } from '../constants/desktop'; import { openCustomProtocol } from './deep-linking'; @@ -44,7 +44,7 @@ export async function getErrorHtml( errorKey, supportLink, metamaskState, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) err, ///: END:ONLY_INCLUDE_IN ) { @@ -65,7 +65,7 @@ export async function getErrorHtml( const { currentLocaleMessages, enLocaleMessages } = response; const t = getLocaleContext(currentLocaleMessages, enLocaleMessages); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) const isDesktopEnabled = metamaskState?.desktopEnabled === true; if (isDesktopEnabled) { @@ -120,7 +120,7 @@ export async function getErrorHtml( `; } -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(desktop) export const MMD_DOWNLOAD_LINK = 'https://github.com/MetaMask/metamask-desktop/releases'; diff --git a/shared/lib/ui-utils.js b/shared/lib/ui-utils.js index 5fbac0b74..4cbc5fddf 100644 --- a/shared/lib/ui-utils.js +++ b/shared/lib/ui-utils.js @@ -1,14 +1,6 @@ -let _supportLink = 'https://support.metamask.io'; - -///: BEGIN:ONLY_INCLUDE_IN(mmi) -_supportLink = 'https://mmi-support.zendesk.com/hc/en-us'; -///: END:ONLY_INCLUDE_IN - -///: BEGIN:ONLY_INCLUDE_IN(flask) -_supportLink = 'https://metamask-flask.zendesk.com/hc'; -///: END:ONLY_INCLUDE_IN - -export const SUPPORT_LINK = _supportLink; +// no destructuring as process.env detection stops working +// eslint-disable-next-line prefer-destructuring +export const SUPPORT_LINK = process.env.SUPPORT_LINK; export const COINGECKO_LINK = 'https://www.coingecko.com/'; export const CRYPTOCOMPARE_LINK = 'https://www.cryptocompare.com/'; diff --git a/shared/modules/hash.utils.ts b/shared/modules/hash.utils.ts new file mode 100644 index 000000000..e27257508 --- /dev/null +++ b/shared/modules/hash.utils.ts @@ -0,0 +1,11 @@ +/* eslint-disable no-undef */ +export async function sha256(str: string): Promise { + const buf = await crypto.subtle.digest( + 'SHA-256', + new TextEncoder().encode(str), + ); + + return Array.prototype.map + .call(new Uint8Array(buf), (x: number) => `00${x.toString(16)}`.slice(-2)) + .join(''); +} diff --git a/shared/modules/transaction.utils.js b/shared/modules/transaction.utils.js index 70f6064ca..b07d1f869 100644 --- a/shared/modules/transaction.utils.js +++ b/shared/modules/transaction.utils.js @@ -176,6 +176,8 @@ export async function determineTransactionType(txParams, query) { contractCode = resultCode; if (isContractAddress) { + const hasValue = txParams.value && txParams.value !== '0x0'; + const tokenMethodName = [ TransactionType.tokenMethodApprove, TransactionType.tokenMethodSetApprovalForAll, @@ -184,13 +186,8 @@ export async function determineTransactionType(txParams, query) { TransactionType.tokenMethodSafeTransferFrom, ].find((methodName) => isEqualCaseInsensitive(methodName, name)); - const isSendWithApprove = - txParams.value && - txParams.value !== '0x0' && - tokenMethodName === TransactionType.tokenMethodApprove; - result = - data && tokenMethodName && !isSendWithApprove + data && tokenMethodName && !hasValue ? tokenMethodName : TransactionType.contractInteraction; } else { diff --git a/shared/modules/transaction.utils.test.js b/shared/modules/transaction.utils.test.js index 4c01f6089..615fda2e3 100644 --- a/shared/modules/transaction.utils.test.js +++ b/shared/modules/transaction.utils.test.js @@ -135,7 +135,7 @@ describe('Transaction.utils', function () { }); }); - it('should return a token transfer type when the recipient is a contract and data is for the respective method call', async function () { + it('should return a token transfer type when the recipient is a contract, there is no value passed, and data is for the respective method call', async function () { const _providerResultStub = { // 1 gwei eth_gasPrice: '0x0de0b6b3a7640000', @@ -159,6 +159,48 @@ describe('Transaction.utils', function () { }); }); + it( + 'should NOT return a token transfer type and instead return contract interaction' + + ' when the recipient is a contract, the data matches the respective method call, but there is a value passed', + async function () { + const _providerResultStub = { + // 1 gwei + eth_gasPrice: '0x0de0b6b3a7640000', + // by default, all accounts are external accounts (not contracts) + eth_getCode: '0xab', + }; + const _provider = createTestProviderTools({ + scaffold: _providerResultStub, + }).provider; + + const resultWithEmptyValue = await determineTransactionType( + { + value: '0x0', + to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', + data: '0xa9059cbb0000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C970000000000000000000000000000000000000000000000000000000000000000a', + }, + new EthQuery(_provider), + ); + expect(resultWithEmptyValue).toMatchObject({ + type: TransactionType.tokenMethodTransfer, + getCodeResponse: '0xab', + }); + + const resultWithValue = await determineTransactionType( + { + value: '0x12345', + to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', + data: '0xa9059cbb0000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C970000000000000000000000000000000000000000000000000000000000000000a', + }, + new EthQuery(_provider), + ); + expect(resultWithValue).toMatchObject({ + type: TransactionType.contractInteraction, + getCodeResponse: '0xab', + }); + }, + ); + it('should NOT return a token transfer type when the recipient is not a contract but the data matches the respective method call', async function () { const _providerResultStub = { // 1 gwei diff --git a/test/data/mock-send-state.json b/test/data/mock-send-state.json index a8d379dcd..0193c3ce5 100644 --- a/test/data/mock-send-state.json +++ b/test/data/mock-send-state.json @@ -115,7 +115,7 @@ "showIncomingTransactions": true }, "network": "5", - "provider": { + "providerConfig": { "type": "rpc", "chainId": "0x5" }, diff --git a/test/data/mock-state.json b/test/data/mock-state.json index b7a08d5c5..b2a446938 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -57,7 +57,43 @@ "priorityFeeTrend": "down", "networkCongestion": 0.90625 }, - "snaps": [{}], + "snaps": { + "npm:@metamask/test-snap-bip44": { + "id": "npm:@metamask/test-snap-bip44", + "origin": "npm:@metamask/test-snap-bip44", + "version": "5.1.2", + "iconUrl": null, + "initialPermissions": { + "endowment:ethereum-provider": {} + }, + "manifest": { + "description": "An example Snap that signs messages using BLS.", + "proposedName": "BIP-44 Test Snap", + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/test-snaps.git" + }, + "source": { + "location": { + "npm": { + "filePath": "dist/bundle.js", + "packageName": "@metamask/test-snap-bip44", + "registry": "https://registry.npmjs.org" + } + }, + "shasum": "L1k+dT9Q+y3KfIqzaH09MpDZVPS9ZowEh9w01ZMTWMU=" + }, + "version": "5.1.2" + }, + "versionHistory": [ + { + "date": 1680686075921, + "origin": "https://metamask.github.io", + "version": "5.1.2" + } + ] + } + }, "preferences": { "hideZeroBalanceTokens": false, "showFiatInTestnets": false, @@ -75,7 +111,7 @@ }, "networkId": "5", "networkStatus": "available", - "provider": { + "providerConfig": { "type": "rpc", "chainId": "0x5", "ticker": "ETH", diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js index aeecb1388..d82b2ef45 100644 --- a/test/e2e/fixture-builder.js +++ b/test/e2e/fixture-builder.js @@ -140,7 +140,8 @@ function defaultFixture() { browserEnvironment: {}, nftsDropdownState: {}, connectedStatusPopoverHasBeenShown: true, - termsOfUseLastAgreed: 86400000000000, + termsOfUseLastAgreed: + '__FIXTURE_SUBSTITUTION__currentDateInMilliseconds', defaultHomeActiveTabName: null, fullScreenGasPollTokens: [], notificationGasPollTokens: [], @@ -196,7 +197,7 @@ function defaultFixture() { NetworkController: { networkId: '1337', networkStatus: 'available', - provider: { + providerConfig: { chainId: CHAIN_IDS.LOCALHOST, nickname: 'Localhost 8545', rpcPrefs: {}, @@ -328,7 +329,7 @@ function onboardingFixture() { NetworkController: { networkId: '1337', networkStatus: 'available', - provider: { + providerConfig: { ticker: 'ETH', type: 'rpc', rpcUrl: 'http://localhost:8545', diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index 1dfccf73f..bc46e568f 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -10,7 +10,6 @@ const FixtureServer = require('./fixture-server'); const PhishingWarningPageServer = require('./phishing-warning-page-server'); const { buildWebDriver } = require('./webdriver'); const { PAGES } = require('./webdriver/driver'); -const { ensureXServerIsRunning } = require('./x-server'); const GanacheSeeder = require('./seeder/ganache-seeder'); const tinyDelayMs = 200; @@ -107,12 +106,7 @@ async function withFixtures(options, testSuite) { } const mockedEndpoint = await setupMocking(mockServer, testSpecificMock); await mockServer.start(8000); - if ( - process.env.SELENIUM_BROWSER === 'chrome' && - process.env.CI === 'true' - ) { - await ensureXServerIsRunning(); - } + driver = (await buildWebDriver(driverOptions)).driver; webDriver = driver.driver; diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index e3a53ffdd..c2b630c8f 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -11,7 +11,6 @@ const { } = require('./helpers'); const { buildWebDriver } = require('./webdriver'); const Ganache = require('./ganache'); -const { ensureXServerIsRunning } = require('./x-server'); const ganacheServer = new Ganache(); const dappPort = 8080; @@ -45,12 +44,6 @@ describe('MetaMask', function () { dappServer.on('listening', resolve); dappServer.on('error', reject); }); - if ( - process.env.SELENIUM_BROWSER === 'chrome' && - process.env.CI === 'true' - ) { - await ensureXServerIsRunning(); - } const result = await buildWebDriver(); driver = result.driver; await driver.navigate(); diff --git a/test/e2e/mv3/service-worker-restart.spec.js b/test/e2e/mv3/service-worker-restart.spec.js new file mode 100644 index 000000000..f33878f88 --- /dev/null +++ b/test/e2e/mv3/service-worker-restart.spec.js @@ -0,0 +1,256 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); +const { + ACTION_QUEUE_METRICS_E2E_TEST, +} = require('../../../shared/constants/test-flags'); +const { + MetaMetricsEventName, + MetaMetricsEventCategory, +} = require('../../../shared/constants/metametrics'); + +const PRIVATE_KEY = + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC'; + +const generateETHBalance = (eth) => convertToHexValue(eth * 10 ** 18); +const defaultGanacheOptions = { + accounts: [{ secretKey: PRIVATE_KEY, balance: generateETHBalance(25) }], +}; + +const numberOfSegmentRequests = 3; + +async function mockSegment(mockServer) { + return await mockServer + .forPost('https://api.segment.io/v1/batch') + .withJsonBodyIncluding({ + batch: [ + { + event: MetaMetricsEventName.ServiceWorkerRestarted, + }, + ], + }) + .times(numberOfSegmentRequests) + .thenCallback(() => { + return { + statusCode: 200, + }; + }); +} + +describe('MV3 - Service worker restart', function () { + let windowHandles; + const driverOptions = { openDevToolsForTabs: true }; + + it('should continue to add new a account when service worker can not restart immediately', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withMetaMetricsController({ + metaMetricsId: 'fake-metrics-id', + participateInMetaMetrics: true, + }) + .withAppStateController({ + [ACTION_QUEUE_METRICS_E2E_TEST]: true, + }) + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test.title, + // because of segment + failOnConsoleError: false, + testSpecificMock: mockSegment, + driverOptions, + }, + async ({ driver, mockedEndpoint }) => { + await driver.navigate(); + + // unlock wallet + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // open the account menu + await driver.clickElement('[data-testid="account-menu-icon"]'); + await driver.clickElement({ text: 'Create account', tag: 'div' }); + + await driver.fill('.new-account-create-form__input', 'Test Account'); + + await driver.clickElement({ text: 'Create', tag: 'button' }); + + await driver.openNewPage('chrome://inspect/#service-workers/'); + await driver.clickElement({ + text: 'Service workers', + tag: 'button', + }); + + await driver.clickElement({ + text: 'terminate', + tag: 'span', + }); + + windowHandles = await driver.getAllWindowHandles(); + const extension = windowHandles[0]; + await driver.switchToWindow(extension); + + // balance renders + await driver.waitForSelector( + { + css: '[class="eth-overview__primary-container"]', + // balance is 0 because we switched to an empty account + text: '0 ETH', + }, + { timeout: 50_000 }, + ); + + await driver.findElement({ text: '0x097...7950', tag: 'div' }); + + // assert that the segment request has been sent through inspecting the mock + await driver.wait(async () => { + const isPending = await mockedEndpoint.isPending(); + return isPending === false; + }, 10_000); + const mockedRequests = await mockedEndpoint.getSeenRequests(); + + assert.equal(mockedRequests.length, numberOfSegmentRequests); + + await assertSWRestartTimeEvent(mockedRequests[0]); + await assertSWRestartTimeEvent(mockedRequests[1]); + await assertSWProcessActionQueueEvent( + mockedRequests[2], + 'addNewAccount', + ); + }, + ); + }); + + it('should restore the transaction when service worker restarts', async function () { + await withFixtures( + { + dapp: true, + fixtures: new FixtureBuilder() + .withPermissionControllerConnectedToTestDapp() + .build(), + ganacheOptions: defaultGanacheOptions, + title: this.test.title, + // because of segment + failOnConsoleError: false, + driverOptions, + }, + async ({ driver }) => { + await driver.navigate(); + // log in wallet + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // initialize a transaction of send from dapp + await driver.openNewPage('http://127.0.0.1:8080'); + await driver.clickElement('#sendButton'); + + // A popup window is initialized + windowHandles = await driver.getAllWindowHandles(); + await driver.waitUntilXWindowHandles(4); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + + // Assert recipient and eth quantity are correct + await assertTransactionDetails(driver); + + // Restart service worker in a new window + // Because if we stay in the same window we will lose the popup when opening a new tab + await driver.switchToNewWindow(); + await driver.openNewURL('chrome://inspect/#service-workers'); + windowHandles = await driver.getAllWindowHandles(); + // MM expanded view, Dapp, Notification popup, console and service worker + await driver.waitUntilXWindowHandles(5); + await driver.clickElement({ + text: 'terminate', + tag: 'span', + }); + + // Should still have only 1 popup + windowHandles = await driver.getAllWindowHandles(); + await driver.waitUntilXWindowHandles(5); + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + + // And popup has the same value + await assertTransactionDetails(driver); + + // Confirm the transaction + await driver.clickElement({ text: 'Confirm', tag: 'button' }); + await driver.switchToWindowWithTitle('MetaMask', windowHandles); + await driver.clickElement('[data-testid="home__activity-tab"]'); + await driver.wait(async () => { + const confirmedTxes = await driver.findElements( + '.transaction-list__completed-transactions .transaction-list-item', + ); + return confirmedTxes.length === 1; + }, 10000); + }, + ); + }); +}); + +async function assertSWRestartTimeEvent(request) { + assert.equal(request.url, 'https://api.segment.io/v1/batch'); + + assert.equal(request.body.json.batch.length, 1); + + const [firstResult] = request.body.json.batch; + + assert.equal(firstResult.event, MetaMetricsEventName.ServiceWorkerRestarted); + + assert.equal( + typeof firstResult.properties.service_worker_restarted_time, + 'number', + ); + + assert.equal(firstResult.properties.service_worker_restarted_time > 0, true); + assert.equal( + firstResult.properties.category, + MetaMetricsEventCategory.ServiceWorkers, + ); + assert.equal(firstResult.properties.chain_id, convertToHexValue(1337)); + assert.equal(firstResult.properties.environment_type, 'background'); + assert.equal(firstResult.properties.locale, 'en'); +} + +async function assertSWProcessActionQueueEvent(request, method) { + assert.equal(request.url, 'https://api.segment.io/v1/batch'); + + assert.equal(request.body.json.batch.length, 1); + + const [firstResult] = request.body.json.batch; + + assert.equal(firstResult.event, MetaMetricsEventName.ServiceWorkerRestarted); + + assert.equal( + firstResult.properties.service_worker_action_queue_methods.indexOf( + method, + ) !== '-1', + true, + ); + assert.equal( + firstResult.properties.category, + MetaMetricsEventCategory.ServiceWorkers, + ); + assert.equal(firstResult.properties.chain_id, convertToHexValue(1337)); + assert.equal(firstResult.properties.environment_type, 'background'); + assert.equal(firstResult.properties.locale, 'en'); +} + +async function assertTransactionDetails(driver) { + const TRUNCATED_RECIPIENT_ADDRESS = '0x0c5...AaFb'; + const recipientAddress = await driver.findElement( + '[data-testid="sender-to-recipient__name"]', + ); + assert.equal(await recipientAddress.getText(), TRUNCATED_RECIPIENT_ADDRESS); + const transactionAmounts = await driver.findElements( + '.currency-display-component__text', + ); + const transactionAmount = transactionAmounts[0]; + assert.equal(await transactionAmount.getText(), '0'); +} diff --git a/test/e2e/seeder/smart-contracts.js b/test/e2e/seeder/smart-contracts.js index fe0f0262a..48d472b4e 100644 --- a/test/e2e/seeder/smart-contracts.js +++ b/test/e2e/seeder/smart-contracts.js @@ -14,7 +14,7 @@ const { } = require('@metamask/test-dapp/dist/constants.json'); const hstFactory = { - initialAmount: 100, + initialAmount: 10, tokenName: 'TST', decimalUnits: 4, tokenSymbol: 'TST', diff --git a/test/e2e/snaps/enums.js b/test/e2e/snaps/enums.js index ec89f5314..0835e9241 100644 --- a/test/e2e/snaps/enums.js +++ b/test/e2e/snaps/enums.js @@ -1,3 +1,3 @@ module.exports = { - TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/5.1.2/', + TEST_SNAPS_WEBSITE_URL: 'https://metamask.github.io/test-snaps/5.2.0/', }; diff --git a/test/e2e/snaps/test-snap-management.spec.js b/test/e2e/snaps/test-snap-management.spec.js index cb44e7d57..98503cadc 100644 --- a/test/e2e/snaps/test-snap-management.spec.js +++ b/test/e2e/snaps/test-snap-management.spec.js @@ -92,6 +92,10 @@ describe('Test Snap Management', function () { await driver.delay(1000); // try to disable the snap + await driver.clickElement({ + text: 'Notification Test Snap', + tag: 'p', + }); await driver.clickElement('.toggle-button > div'); // switch back to test-snaps window @@ -130,12 +134,11 @@ describe('Test Snap Management', function () { ); assert.equal(await notificationResult.getText(), '1'); - // click on see details - await driver.clickElement({ text: 'See details', tag: 'button' }); - await driver.delay(1000); - // try to remove snap - await driver.clickElement({ text: 'Remove snap', tag: 'button' }); + await driver.clickElement({ + text: 'Remove Notification Test Snap', + tag: 'p', + }); await driver.delay(1000); // try to click remove on popover diff --git a/test/e2e/snaps/test-snap-wasm.spec.js b/test/e2e/snaps/test-snap-wasm.spec.js new file mode 100644 index 000000000..55326ac32 --- /dev/null +++ b/test/e2e/snaps/test-snap-wasm.spec.js @@ -0,0 +1,92 @@ +const { withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); +const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); + +describe('Test Snap WASM', function () { + it('can use webassembly inside a snap', async function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + }; + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + ganacheOptions, + failOnConsoleError: false, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + + // enter pw into extension + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // navigate to test snaps page and connect + await driver.openNewPage(TEST_SNAPS_WEBSITE_URL); + await driver.delay(1000); + const snapButton = await driver.findElement('#connectWasmSnap'); + await driver.scrollToElement(snapButton); + await driver.delay(1000); + await driver.clickElement('#connectWasmSnap'); + await driver.delay(1000); + + // switch to metamask extension and click connect + const windowHandles = await driver.waitUntilXWindowHandles( + 3, + 1000, + 10000, + ); + // const extensionPage = windowHandles[0]; + await driver.switchToWindowWithTitle( + 'MetaMask Notification', + windowHandles, + ); + await driver.clickElement({ + text: 'Connect', + tag: 'button', + }); + + await driver.waitForSelector({ text: 'Approve & install' }); + + await driver.clickElement({ + text: 'Approve & install', + tag: 'button', + }); + + await driver.waitForSelector({ text: 'Ok' }); + + await driver.clickElement({ + text: 'Ok', + tag: 'button', + }); + + // click send inputs on test snap page + await driver.switchToWindowWithTitle('Test Snaps', windowHandles); + + // wait for npm installation success + await driver.waitForSelector({ + css: '#connectWasmSnap', + text: 'Reconnect to WebAssembly Snap', + }); + + // enter number for test to input field + await driver.pasteIntoField('#wasmInput', '23'); + + // find and click on send error + await driver.clickElement('#sendWasmMessage'); + + // wait for the correct output + await driver.waitForSelector({ + css: '#wasmResult', + text: '28657', + }); + }, + ); + }); +}); diff --git a/test/e2e/tests/ens.spec.js b/test/e2e/tests/ens.spec.js index 136f06df1..be48816c9 100644 --- a/test/e2e/tests/ens.spec.js +++ b/test/e2e/tests/ens.spec.js @@ -80,7 +80,7 @@ describe('ENS', function () { { fixtures: new FixtureBuilder() .withNetworkController({ - provider: { + providerConfig: { chainId: '0x1', nickname: '', rpcUrl: '', diff --git a/test/e2e/tests/metamask-responsive-ui.spec.js b/test/e2e/tests/metamask-responsive-ui.spec.js index e21668a10..66b1a9cfc 100644 --- a/test/e2e/tests/metamask-responsive-ui.spec.js +++ b/test/e2e/tests/metamask-responsive-ui.spec.js @@ -4,7 +4,7 @@ const FixtureBuilder = require('../fixture-builder'); describe('MetaMask Responsive UI', function () { it('Creating a new wallet', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { openDevToolsForTabs: true }; await withFixtures( { @@ -75,7 +75,7 @@ describe('MetaMask Responsive UI', function () { }); it('Importing existing wallet from lock page', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { openDevToolsForTabs: true }; const testSeedPhrase = 'phrase upgrade clock rough situate wedding elder clever doctor stamp excess tent'; @@ -116,7 +116,7 @@ describe('MetaMask Responsive UI', function () { }); it('Send Transaction from responsive window', async function () { - const driverOptions = { responsive: true }; + const driverOptions = { openDevToolsForTabs: true }; const ganacheOptions = { accounts: [ { diff --git a/test/e2e/tests/portfolio-site.spec.js b/test/e2e/tests/portfolio-site.spec.js index 06b47ce4b..2bdb413d5 100644 --- a/test/e2e/tests/portfolio-site.spec.js +++ b/test/e2e/tests/portfolio-site.spec.js @@ -34,7 +34,7 @@ describe('Portfolio site', function () { // Verify site assert.equal( await driver.getCurrentUrl(), - 'http://127.0.0.1:8080/?metamaskEntry=ext', + 'http://127.0.0.1:8080/?metamaskEntry=ext&metametricsId=null', ); }, ); diff --git a/test/e2e/tests/send-eth.spec.js b/test/e2e/tests/send-eth.spec.js index fbc84854b..56c9f744c 100644 --- a/test/e2e/tests/send-eth.spec.js +++ b/test/e2e/tests/send-eth.spec.js @@ -336,11 +336,11 @@ describe('Send ETH from dapp using advanced gas controls', function () { await driver.clickElement({ text: 'Save', tag: 'button' }); await driver.waitForSelector({ css: '.transaction-detail-item:nth-of-type(1) h6:nth-of-type(2)', - text: '0.02367237 ETH', + text: '0.04503836 ETH', }); await driver.waitForSelector({ css: '.transaction-detail-item:nth-of-type(2) h6:nth-of-type(2)', - text: '0.02367237 ETH', + text: '0.04503836 ETH', }); await driver.clickElement({ text: 'Confirm', tag: 'button' }); diff --git a/test/e2e/tests/send-hex-address.spec.js b/test/e2e/tests/send-hex-address.spec.js index 08d7b2c1d..c971f4f01 100644 --- a/test/e2e/tests/send-hex-address.spec.js +++ b/test/e2e/tests/send-hex-address.spec.js @@ -155,7 +155,7 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { }); await driver.waitForSelector({ css: '.transaction-detail-item', - text: '0.00008346 ETH', + text: '0.00008455 ETH', }); await driver.clickElement({ text: 'Next', tag: 'button' }); @@ -220,7 +220,7 @@ describe('Send ERC20 to a 40 character hexadecimal address', function () { }); await driver.waitForSelector({ css: '.transaction-detail-item', - text: '0.00008346 ETH', + text: '0.00008455 ETH', }); await driver.clickElement({ text: 'Next', tag: 'button' }); diff --git a/test/e2e/tests/settings-search.spec.js b/test/e2e/tests/settings-search.spec.js index d694a34bf..c4af0ccc2 100644 --- a/test/e2e/tests/settings-search.spec.js +++ b/test/e2e/tests/settings-search.spec.js @@ -19,7 +19,7 @@ describe('Settings Search', function () { security: 'Reveal Secret', alerts: 'Browsing a website', networks: 'Ethereum Mainnet', - experimental: 'Enable transaction security', + experimental: 'Enable security alerts', about: 'Terms of Use', }; diff --git a/test/e2e/tests/terms-of-use.spec.js b/test/e2e/tests/terms-of-use.spec.js new file mode 100644 index 000000000..f224cb55a --- /dev/null +++ b/test/e2e/tests/terms-of-use.spec.js @@ -0,0 +1,45 @@ +const { strict: assert } = require('assert'); +const { convertToHexValue, withFixtures } = require('../helpers'); +const FixtureBuilder = require('../fixture-builder'); + +describe('Terms of use', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + }; + it('accepts the updated terms of use', async function () { + const firstOfJan = 1672574400; + await withFixtures( + { + fixtures: new FixtureBuilder() + .withAppStateController({ + termsOfUseLastAgreed: firstOfJan, + }) + .build(), + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + // accept updated terms of use + const acceptTerms = '[data-testid="terms-of-use-accept-button"]'; + await driver.clickElement('[data-testid="popover-scroll-button"]'); + await driver.clickElement('[data-testid="terms-of-use-checkbox"]'); + await driver.clickElement(acceptTerms); + + // check modal is no longer shown + await driver.waitForElementNotPresent(acceptTerms); + const termsExists = await driver.isElementPresent(acceptTerms); + assert.equal(termsExists, false, 'terms of use should not be shown'); + }, + ); + }); +}); diff --git a/test/e2e/webdriver/chrome.js b/test/e2e/webdriver/chrome.js index 09069906c..1b32bd675 100644 --- a/test/e2e/webdriver/chrome.js +++ b/test/e2e/webdriver/chrome.js @@ -13,9 +13,9 @@ const HTTPS_PROXY_HOST = '127.0.0.1:8000'; * A wrapper around a {@code WebDriver} instance exposing Chrome-specific functionality */ class ChromeDriver { - static async build({ responsive, port }) { + static async build({ openDevToolsForTabs, port }) { const args = [`load-extension=dist/chrome`]; - if (responsive) { + if (openDevToolsForTabs) { args.push('--auto-open-devtools-for-tabs'); } diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index 2b2fcb386..ba555177a 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -337,10 +337,13 @@ class Driver { } // Window management + async openNewURL(url) { + await this.driver.get(url); + } async openNewPage(url) { const newHandle = await this.driver.switchTo().newWindow(); - await this.driver.get(url); + await this.openNewURL(url); return newHandle; } @@ -348,6 +351,10 @@ class Driver { await this.driver.switchTo().window(handle); } + async switchToNewWindow() { + await this.driver.switchTo().newWindow('window'); + } + async switchToFrame(element) { await this.driver.switchTo().frame(element); } diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index 6bb90b9ab..52e936f09 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -42,6 +42,9 @@ class FirefoxDriver { 'browser.download.dir', `${process.cwd()}/test-artifacts/downloads`, ); + if (process.env.CI === 'true') { + options.setBinary('/opt/firefox/firefox'); + } const builder = new Builder() .forBrowser('firefox') .setFirefoxOptions(options); diff --git a/test/e2e/webdriver/index.js b/test/e2e/webdriver/index.js index ebec9a002..aeb6bc964 100644 --- a/test/e2e/webdriver/index.js +++ b/test/e2e/webdriver/index.js @@ -3,14 +3,14 @@ const Driver = require('./driver'); const ChromeDriver = require('./chrome'); const FirefoxDriver = require('./firefox'); -async function buildWebDriver({ responsive, port, timeOut } = {}) { +async function buildWebDriver({ openDevToolsForTabs, port, timeOut } = {}) { const browser = process.env.SELENIUM_BROWSER; const { driver: seleniumDriver, extensionId, extensionUrl, - } = await buildBrowserWebDriver(browser, { responsive, port }); + } = await buildBrowserWebDriver(browser, { openDevToolsForTabs, port }); const driver = new Driver(seleniumDriver, browser, extensionUrl, timeOut); return { diff --git a/test/e2e/x-server.js b/test/e2e/x-server.js deleted file mode 100644 index 9be32b099..000000000 --- a/test/e2e/x-server.js +++ /dev/null @@ -1,17 +0,0 @@ -const { runCommand } = require('../../development/lib/run-command'); -const { retry } = require('../../development/lib/retry'); - -function ensureXServerIsRunning() { - return retry( - { - retries: 3, - delay: 2000, - rejectionMessage: 'X server does not seem to be running?!', - }, - () => { - return runCommand('xset', ['q']); - }, - ); -} - -module.exports = { ensureXServerIsRunning }; diff --git a/test/env.js b/test/env.js index 38e4a6fed..fd055ee8a 100644 --- a/test/env.js +++ b/test/env.js @@ -1 +1,2 @@ -process.env.METAMASK_ENV = 'test'; +process.env.METAMASK_ENVIRONMENT = 'test'; +process.env.SUPPORT_LINK = 'https://support.metamask.io'; diff --git a/test/helpers/protect-intrinsics-helpers.js b/test/helpers/protect-intrinsics-helpers.js index 1d71fc8ee..6c30b4291 100644 --- a/test/helpers/protect-intrinsics-helpers.js +++ b/test/helpers/protect-intrinsics-helpers.js @@ -13,14 +13,10 @@ module.exports = { function getGlobalProperties() { const comp = new Compartment().globalThis; - // These are Agoric inventions, and we don't care about them. const ignoreList = new Set([ 'Compartment', - 'HandledPromise', - 'StaticModuleRecord', ...Object.getOwnPropertySymbols(comp), ]); - const namedIntrinsics = Reflect.ownKeys(comp); return new Set( diff --git a/test/helpers/setup-helper.js b/test/helpers/setup-helper.js index 75da079f3..0767a0056 100644 --- a/test/helpers/setup-helper.js +++ b/test/helpers/setup-helper.js @@ -78,6 +78,7 @@ window.document.body.appendChild(popoverContent); // eslint-disable-next-line no-shadow const fetch = require('node-fetch'); +/* eslint-disable-next-line no-shadow */ const { Headers, Request, Response } = fetch; Object.assign(window, { fetch, Headers, Request, Response }); diff --git a/test/jest/mock-store.js b/test/jest/mock-store.js index 80c477a10..80934403b 100644 --- a/test/jest/mock-store.js +++ b/test/jest/mock-store.js @@ -137,7 +137,7 @@ export const createSwapsMockStore = () => { 1559: false, }, }, - provider: { + providerConfig: { chainId: CHAIN_IDS.MAINNET, }, cachedBalances: { diff --git a/test/unit-global/protect-intrinsics.test.js b/test/unit-global/protect-intrinsics.test.js index c3cd02a29..df89121c0 100644 --- a/test/unit-global/protect-intrinsics.test.js +++ b/test/unit-global/protect-intrinsics.test.js @@ -1,4 +1,4 @@ -import 'ses/lockdown'; +import 'ses'; import '../../app/scripts/lockdown-run'; import '../../app/scripts/lockdown-more'; import { diff --git a/types/eth-keyring-controller.d.ts b/types/eth-keyring-controller.d.ts index 81145fa60..ee7525bf3 100644 --- a/types/eth-keyring-controller.d.ts +++ b/types/eth-keyring-controller.d.ts @@ -11,5 +11,7 @@ declare module '@metamask/eth-keyring-controller' { }>; getEncryptionPublicKey: (address: string) => Promise; + + decryptMessage: (...any) => any; } } diff --git a/ui/components/app/account-menu/account-menu.component.js b/ui/components/app/account-menu/account-menu.component.js index 7c0b98bc3..37f5c5a6b 100644 --- a/ui/components/app/account-menu/account-menu.component.js +++ b/ui/components/app/account-menu/account-menu.component.js @@ -17,7 +17,7 @@ import SiteIcon from '../../ui/site-icon'; import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; import { PRIMARY, - ///: BEGIN:ONLY_INCLUDE_IN(beta,flask) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta,build-flask) SUPPORT_REQUEST_LINK, ///: END:ONLY_INCLUDE_IN } from '../../../helpers/constants/common'; @@ -27,7 +27,7 @@ import { IMPORT_ACCOUNT_ROUTE, CONNECT_HARDWARE_ROUTE, DEFAULT_ROUTE, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) NOTIFICATIONS_ROUTE, ///: END:ONLY_INCLUDE_IN } from '../../../helpers/constants/routes'; @@ -88,7 +88,7 @@ export default class AccountMenu extends Component { toggleAccountMenu: PropTypes.func, addressConnectedSubjectMap: PropTypes.object, originOfCurrentTab: PropTypes.string, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount: PropTypes.number, ///: END:ONLY_INCLUDE_IN }; @@ -310,7 +310,7 @@ export default class AccountMenu extends Component { toggleAccountMenu, lockMetamask, history, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount, ///: END:ONLY_INCLUDE_IN } = this.props; @@ -321,7 +321,7 @@ export default class AccountMenu extends Component { let supportText = t('support'); let supportLink = SUPPORT_LINK; - ///: BEGIN:ONLY_INCLUDE_IN(beta,flask) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta,build-flask) supportText = t('needHelpSubmitTicket'); supportLink = SUPPORT_REQUEST_LINK; ///: END:ONLY_INCLUDE_IN @@ -415,7 +415,7 @@ export default class AccountMenu extends Component { />
{ - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) <> { diff --git a/ui/components/app/account-menu/account-menu.container.js b/ui/components/app/account-menu/account-menu.container.js index ce702f0be..72a012105 100644 --- a/ui/components/app/account-menu/account-menu.container.js +++ b/ui/components/app/account-menu/account-menu.container.js @@ -13,7 +13,7 @@ import { getMetaMaskKeyrings, getOriginOfCurrentTab, getSelectedAddress, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) getUnreadNotificationsCount, ///: END:ONLY_INCLUDE_IN } from '../../../selectors'; @@ -31,7 +31,7 @@ function mapStateToProps(state) { const accounts = getMetaMaskAccountsOrdered(state); const origin = getOriginOfCurrentTab(state); const selectedAddress = getSelectedAddress(state); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) const unreadNotificationsCount = getUnreadNotificationsCount(state); ///: END:ONLY_INCLUDE_IN return { @@ -42,7 +42,7 @@ function mapStateToProps(state) { keyrings: getMetaMaskKeyrings(state), accounts, shouldShowAccountsSearch: accounts.length >= SHOW_SEARCH_ACCOUNTS_MIN_COUNT, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount, ///: END:ONLY_INCLUDE_IN }; diff --git a/ui/components/app/account-menu/account-menu.test.js b/ui/components/app/account-menu/account-menu.test.js index 504631350..90a3d6a42 100644 --- a/ui/components/app/account-menu/account-menu.test.js +++ b/ui/components/app/account-menu/account-menu.test.js @@ -43,7 +43,7 @@ const initialProps = { const mockStore = { metamask: { - provider: { + providerConfig: { type: 'test', }, preferences: { diff --git a/ui/components/app/account-menu/keyring-label.js b/ui/components/app/account-menu/keyring-label.js index ea406541f..716ae566a 100644 --- a/ui/components/app/account-menu/keyring-label.js +++ b/ui/components/app/account-menu/keyring-label.js @@ -35,7 +35,7 @@ export default function KeyRingLabel({ keyring }) { label = null; } - ///: BEGIN:ONLY_INCLUDE_IN(mmi) + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) if (type.startsWith('Custody') && /JSONRPC/u.test(type)) { label = type.split(' - ')[1]; return null; diff --git a/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js b/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js index bd6007774..6a15f9c6b 100644 --- a/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js +++ b/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js @@ -7,7 +7,7 @@ import AdvancedGasControls from './advanced-gas-controls.component'; const renderComponent = (props) => { const store = configureMockStore([])({ - metamask: { identities: [], provider: {} }, + metamask: { identities: [], providerConfig: {} }, }); return renderWithProvider(, store); }; diff --git a/ui/components/app/advanced-gas-inputs/advanced-gas-inputs.test.js b/ui/components/app/advanced-gas-inputs/advanced-gas-inputs.test.js index cff1c62d1..c1db0ef69 100644 --- a/ui/components/app/advanced-gas-inputs/advanced-gas-inputs.test.js +++ b/ui/components/app/advanced-gas-inputs/advanced-gas-inputs.test.js @@ -20,7 +20,7 @@ describe('AdvancedGasInputs', () => { minimumGasLimit: 21000, }; - const store = configureStore({ metamask: { provider: {} } }); + const store = configureStore({ metamask: { providerConfig: {} } }); beforeEach(() => { clock = sinon.useFakeTimers(); diff --git a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js index c710da525..10c514743 100644 --- a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js +++ b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js @@ -64,7 +64,7 @@ describe('Unconnected Account Alert', () => { accounts, cachedBalances, keyrings, - provider: { + providerConfig: { chainId: CHAIN_IDS, }, permissionHistory: { diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index 0fb69b866..1a4b9eac3 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -34,15 +34,16 @@ @import 'edit-gas-fee-popover/network-statistics/status-slider/index'; @import 'edit-gas-fee-popover/edit-gas-tooltip/index'; @import 'flask/experimental-area/index'; -@import 'flask/snap-content-footer/index'; -@import 'flask/snap-install-warning/index'; -@import 'flask/snap-remove-warning/index'; -@import 'flask/snap-ui-renderer/index'; -@import 'flask/snap-ui-markdown/index'; -@import 'flask/snap-delineator/index'; -@import 'flask/snap-settings-card/index'; -@import 'flask/update-snap-permission-list/index'; -@import 'flask/copyable/index'; +@import 'snaps/snap-content-footer/index'; +@import 'snaps/snap-install-warning/index'; +@import 'snaps/snap-remove-warning/index'; +@import 'snaps/snap-ui-renderer/index'; +@import 'snaps/snap-ui-markdown/index'; +@import 'snaps/snap-delineator/index'; +@import 'snaps/snap-settings-card/index'; +@import 'snaps/update-snap-permission-list/index'; +@import 'snaps/copyable/index'; +@import 'snaps/snap-version/index'; @import 'gas-details-item/index'; @import 'gas-details-item/gas-details-item-title/index'; @import 'gas-timing/index'; @@ -104,3 +105,8 @@ @import 'network-account-balance-header/index'; @import 'approve-content-card/index'; @import 'transaction-alerts/transaction-alerts'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +@import '../institutional/confirm-remove-jwt-modal/index'; +@import '../institutional/custody-confirm-link-modal/index'; +@import '../institutional/transaction-failed-modal/index'; +///: END:ONLY_INCLUDE_IN diff --git a/ui/components/app/app-header/app-header.component.js b/ui/components/app/app-header/app-header.component.js index 6ef03c773..a430ab0eb 100644 --- a/ui/components/app/app-header/app-header.component.js +++ b/ui/components/app/app-header/app-header.component.js @@ -10,9 +10,9 @@ import { } from '../../../../shared/constants/metametrics'; import NetworkDisplay from '../network-display'; -///: BEGIN:ONLY_INCLUDE_IN(beta) +///: BEGIN:ONLY_INCLUDE_IN(build-beta) import BetaHeader from '../beta-header'; -///: END:ONLY_INCLUDE_IN(beta) +///: END:ONLY_INCLUDE_IN export default class AppHeader extends PureComponent { static propTypes = { @@ -27,14 +27,19 @@ export default class AppHeader extends PureComponent { disabled: PropTypes.bool, disableNetworkIndicator: PropTypes.bool, isAccountMenuOpen: PropTypes.bool, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount: PropTypes.number, + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled: PropTypes.bool, ///: END:ONLY_INCLUDE_IN - ///: BEGIN:ONLY_INCLUDE_IN(beta) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta) showBetaHeader: PropTypes.bool, ///: END:ONLY_INCLUDE_IN onClick: PropTypes.func, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + custodianIcon: PropTypes.string, + ///: END:ONLY_INCLUDE_IN }; static contextTypes = { @@ -77,7 +82,7 @@ export default class AppHeader extends PureComponent { selectedAddress, disabled, isAccountMenuOpen, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount, ///: END:ONLY_INCLUDE_IN } = this.props; @@ -104,7 +109,7 @@ export default class AppHeader extends PureComponent { > { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount > 0 && (
{unreadNotificationsCount} @@ -124,20 +129,24 @@ export default class AppHeader extends PureComponent { disableNetworkIndicator, disabled, onClick, - ///: BEGIN:ONLY_INCLUDE_IN(beta) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta) showBetaHeader, - ///: END:ONLY_INCLUDE_IN(beta) - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + custodianIcon, + isUnlocked, + ///: END:ONLY_INCLUDE_IN } = this.props; return ( <> { - ///: BEGIN:ONLY_INCLUDE_IN(beta) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta) showBetaHeader ? : null - ///: END:ONLY_INCLUDE_IN(beta) + ///: END:ONLY_INCLUDE_IN }
@@ -150,9 +159,13 @@ export default class AppHeader extends PureComponent { } history.push(DEFAULT_ROUTE); }} + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + custodyImgSrc={custodianIcon} + isUnlocked={isUnlocked} + ///: END:ONLY_INCLUDE_IN /> { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled && process.env.METAMASK_DEBUG && (
{ selectedAddress, isUnlocked, isAccountMenuOpen, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN } = metamask; - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const custodianIcon = selectedAddress + ? getCustodianIconForAddress(state, selectedAddress) + : null; + ///: END:ONLY_INCLUDE_IN + + ///: BEGIN:ONLY_INCLUDE_IN(snaps) const unreadNotificationsCount = getUnreadNotificationsCount(state); ///: END:ONLY_INCLUDE_IN - ///: BEGIN:ONLY_INCLUDE_IN(beta) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta) const showBetaHeader = getShowBetaHeader(state); ///: END:ONLY_INCLUDE_IN @@ -38,13 +47,18 @@ const mapStateToProps = (state) => { selectedAddress, isUnlocked, isAccountMenuOpen, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) unreadNotificationsCount, + ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN - ///: BEGIN:ONLY_INCLUDE_IN(beta) + ///: BEGIN:ONLY_INCLUDE_IN(build-beta) showBetaHeader, ///: END:ONLY_INCLUDE_IN + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + custodianIcon, + ///: END:ONLY_INCLUDE_IN }; }; diff --git a/ui/components/app/app-header/index.scss b/ui/components/app/app-header/index.scss index b06486b7a..4bcb08f63 100644 --- a/ui/components/app/app-header/index.scss +++ b/ui/components/app/app-header/index.scss @@ -34,6 +34,20 @@ } } + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + &__custody-logo { + &--icon { + height: 16px; + margin-left: 15px; + margin-top: 4px; + + @media screen and (min-width: $break-large) { + display: none; + } + } + } + ///: END:ONLY_INCLUDE_IN + &__contents { display: flex; flex-flow: row nowrap; diff --git a/ui/components/app/approve-content-card/approve-content-card.js b/ui/components/app/approve-content-card/approve-content-card.js index 8f188b9ba..23b31b4b8 100644 --- a/ui/components/app/approve-content-card/approve-content-card.js +++ b/ui/components/app/approve-content-card/approve-content-card.js @@ -12,9 +12,9 @@ import { BLOCK_SIZES, DISPLAY, FLEX_DIRECTION, - FONT_WEIGHT, + FontWeight, JustifyContent, - TEXT_ALIGN, + TextAlign, TextColor, TextVariant, } from '../../../helpers/constants/design-system'; @@ -135,7 +135,7 @@ export default function ApproveContentCard({ className="approve-content-card-container__transaction-details-extra-content" > {useCurrencyRateCheck && ( @@ -197,7 +197,7 @@ export default function ApproveContentCard({ diff --git a/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js b/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js index 9c9ef6230..e550e881a 100644 --- a/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js +++ b/ui/components/app/asset-list/detected-tokens-link/detected-tokens-link.js @@ -6,7 +6,10 @@ import classNames from 'classnames'; import Box from '../../../ui/box/box'; import Button from '../../../ui/button'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { getDetectedTokensInCurrentNetwork } from '../../../../selectors'; +import { + getCurrentChainId, + getDetectedTokensInCurrentNetwork, +} from '../../../../selectors'; import { MetaMetricsContext } from '../../../../contexts/metametrics'; import { MetaMetricsEventCategory, @@ -23,13 +26,16 @@ const DetectedTokensLink = ({ className = '', setShowDetectedTokens }) => { ({ address, symbol }) => `${symbol} - ${address}`, ); + const chainId = useSelector(getCurrentChainId); + const onClick = () => { setShowDetectedTokens(true); trackEvent({ event: MetaMetricsEventName.TokenImportClicked, category: MetaMetricsEventCategory.Wallet, properties: { - source: MetaMetricsTokenEventSource.Detected, + source_connection_method: MetaMetricsTokenEventSource.Detected, + chain_id: chainId, tokens: detectedTokensDetails, }, }); diff --git a/ui/components/app/beta-header/__snapshots__/beta-header.test.js.snap b/ui/components/app/beta-header/__snapshots__/beta-header.test.js.snap index 7190ad958..72b1c312c 100644 --- a/ui/components/app/beta-header/__snapshots__/beta-header.test.js.snap +++ b/ui/components/app/beta-header/__snapshots__/beta-header.test.js.snap @@ -6,7 +6,7 @@ exports[`Beta Header should match snapshot 1`] = ` class="box beta-header box--padding-2 box--display-flex box--flex-direction-row box--align-items-center box--width-full box--background-color-warning-default" >
diff --git a/ui/components/app/beta-header/index.js b/ui/components/app/beta-header/index.js index 1eb7bfbe0..41352723d 100644 --- a/ui/components/app/beta-header/index.js +++ b/ui/components/app/beta-header/index.js @@ -2,19 +2,24 @@ import React from 'react'; import { useI18nContext } from '../../../hooks/useI18nContext'; import Box from '../../ui/box/box'; -import Typography from '../../ui/typography/typography'; import { - TypographyVariant, + TextVariant, Color, BLOCK_SIZES, DISPLAY, AlignItems, IconColor, + TextColor, } from '../../../helpers/constants/design-system'; import { BETA_BUGS_URL } from '../../../helpers/constants/beta'; import { hideBetaHeader } from '../../../store/actions'; -import { ButtonIcon, ButtonIconSize, IconName } from '../../component-library'; +import { + ButtonIcon, + ButtonIconSize, + IconName, + Text, +} from '../../component-library'; const BetaHeader = () => { const t = useI18nContext(); @@ -28,12 +33,11 @@ const BetaHeader = () => { className="beta-header" alignItems={AlignItems.center} > - {t('betaHeaderText', [ { {t('here')} , ])} - + { @@ -97,9 +96,11 @@ const CancelSpeedupPopover = () => { >
- @@ -127,7 +128,7 @@ const CancelSpeedupPopover = () => { } /> - +
{ if (isMultiLayerFeeNetwork) { return [ { /> } detailText={ - + useCurrencyRateCheck && ( + + ) } noBold flexWidthValues diff --git a/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.test.js b/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.test.js index 2de3c0f54..1d975e19e 100644 --- a/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.test.js +++ b/ui/components/app/confirm-gas-display/confirm-legacy-gas-display/confirm-legacy-gas-display.test.js @@ -111,13 +111,13 @@ describe('ConfirmLegacyGasDisplay', () => { }); it('should contain L1 L2 fee details for optimism', async () => { - mmState.metamask.provider.chainId = CHAIN_IDS.OPTIMISM; + mmState.metamask.providerConfig.chainId = CHAIN_IDS.OPTIMISM; mmState.confirmTransaction.txData.chainId = CHAIN_IDS.OPTIMISM; const state = { metamask: { ...mmState.metamask, - provider: { - ...mmState.metamask.provider, + providerConfig: { + ...mmState.metamask.providerConfig, chainId: CHAIN_IDS.OPTIMISM, }, }, diff --git a/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js index 52c795265..9edd0c53b 100644 --- a/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js @@ -7,7 +7,7 @@ import ConfirmDetailRow from '.'; describe('Confirm Detail Row Component', () => { const mockState = { metamask: { - provider: { + providerConfig: { type: 'rpc', chainId: '0x5', }, diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index c10bb8c06..4a2480646 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -12,6 +12,7 @@ import { TypographyVariant } from '../../../../helpers/constants/design-system'; import SecurityProviderBannerMessage from '../../security-provider-banner-message/security-provider-banner-message'; import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../../security-provider-banner-message/security-provider-banner-message.constants'; +import { getPortfolioUrl } from '../../../../helpers/utils/portfolio'; import { ConfirmPageContainerSummary, ConfirmPageContainerWarning } from '.'; export default class ConfirmPageContainerContent extends Component { @@ -24,7 +25,7 @@ export default class ConfirmPageContainerContent extends Component { dataComponent: PropTypes.node, dataHexComponent: PropTypes.node, detailsComponent: PropTypes.node, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) insightComponent: PropTypes.node, ///: END:ONLY_INCLUDE_IN errorKey: PropTypes.string, @@ -54,12 +55,13 @@ export default class ConfirmPageContainerContent extends Component { transactionType: PropTypes.string, isBuyableChain: PropTypes.bool, txData: PropTypes.object, + metaMetricsId: PropTypes.string, }; renderContent() { const { detailsComponent, dataComponent } = this.props; - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) const { insightComponent } = this.props; if (insightComponent && (detailsComponent || dataComponent)) { @@ -73,7 +75,7 @@ export default class ConfirmPageContainerContent extends Component { return ( detailsComponent || - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) insightComponent || ///: END:ONLY_INCLUDE_IN dataComponent @@ -86,7 +88,7 @@ export default class ConfirmPageContainerContent extends Component { detailsComponent, dataComponent, dataHexComponent, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) insightComponent, ///: END:ONLY_INCLUDE_IN } = this.props; @@ -120,7 +122,7 @@ export default class ConfirmPageContainerContent extends Component { )} { - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) insightComponent ///: END:ONLY_INCLUDE_IN } @@ -159,14 +161,13 @@ export default class ConfirmPageContainerContent extends Component { transactionType, isBuyableChain, txData, + metaMetricsId, } = this.props; const { t } = this.context; const showInsuffienctFundsError = - supportsEIP1559 && - (errorKey || errorMessage) && - errorKey === INSUFFICIENT_FUNDS_ERROR_KEY; + (errorKey || errorMessage) && errorKey === INSUFFICIENT_FUNDS_ERROR_KEY; return (
{this.renderContent()} - {!supportsEIP1559 && (errorKey || errorMessage) && ( -
- -
- )} + {!supportsEIP1559 && + !showInsuffienctFundsError && + (errorKey || errorMessage) && ( +
+ +
+ )} {showInsuffienctFundsError && (
{ - const portfolioUrl = process.env.PORTFOLIO_URL; global.platform.openTab({ - url: `${portfolioUrl}/buy?metamaskEntry=ext_buy_button`, + url: getPortfolioUrl( + 'buy', + 'ext_buy_button', + metaMetricsId, + ), }); }} key={`${nativeCurrency}-buy-button`} diff --git a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.test.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.test.js index 7074382d9..1814751fe 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.test.js @@ -3,14 +3,17 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import { TransactionType } from '../../../../../shared/constants/transaction'; import { renderWithProvider } from '../../../../../test/lib/render-helpers'; -import { TRANSACTION_ERROR_KEY } from '../../../../helpers/constants/error-keys'; +import { + INSUFFICIENT_FUNDS_ERROR_KEY, + TRANSACTION_ERROR_KEY, +} from '../../../../helpers/constants/error-keys'; import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../../security-provider-banner-message/security-provider-banner-message.constants'; import ConfirmPageContainerContent from './confirm-page-container-content.component'; describe('Confirm Page Container Content', () => { const mockStore = { metamask: { - provider: { + providerConfig: { type: 'test', chainId: '0x5', }, @@ -147,9 +150,7 @@ describe('Confirm Page Container Content', () => { 'Because of an error, this request was not verified by the security provider. Proceed with caution.', ), ).toBeInTheDocument(); - expect( - queryByText('This is based on information from'), - ).toBeInTheDocument(); + expect(queryByText('OpenSea')).toBeInTheDocument(); }); it('should not render SecurityProviderBannerMessage component when flagAsDangerous is not malicious', () => { @@ -168,6 +169,32 @@ describe('Confirm Page Container Content', () => { 'Because of an error, this request was not verified by the security provider. Proceed with caution.', ), ).toBeNull(); - expect(queryByText('This is based on information from')).toBeNull(); + expect(queryByText('OpenSea')).toBeNull(); + }); + + it('should show insufficient funds error for EIP-1559 network', () => { + const { getByRole } = renderWithProvider( + , + store, + ); + expect(getByRole('button', { name: 'Buy' })).toBeInTheDocument(); + }); + + it('should show insufficient funds error for legacy network', () => { + const { getByRole } = renderWithProvider( + , + store, + ); + expect(getByRole('button', { name: 'Buy' })).toBeInTheDocument(); }); }); diff --git a/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js index e616f04a4..cca653ded 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js @@ -13,7 +13,7 @@ describe('Confirm Detail Row Component', () => { const mockState = { metamask: { networkStatus: 'available', - provider: { + providerConfig: { type: 'rpc', chainId: '0x5', }, diff --git a/ui/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js index 1c9b74d6a..5ae5819ea 100644 --- a/ui/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -11,7 +11,9 @@ import { import { NETWORK_TO_NAME_MAP } from '../../../../shared/constants/network'; import { PageContainerFooter } from '../../ui/page-container'; +///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) import Button from '../../ui/button'; +///: END:ONLY_INCLUDE_IN import ActionableMessage from '../../ui/actionable-message/actionable-message'; import SenderToRecipient from '../../ui/sender-to-recipient'; @@ -30,15 +32,16 @@ import NetworkAccountBalanceHeader from '../network-account-balance-header/netwo import { fetchTokenBalance } from '../../../../shared/lib/token-util.ts'; import SetApproveForAllWarning from '../set-approval-for-all-warning'; import { useI18nContext } from '../../../hooks/useI18nContext'; -///: BEGIN:ONLY_INCLUDE_IN(flask) +///: BEGIN:ONLY_INCLUDE_IN(snaps) import useTransactionInsights from '../../../hooks/useTransactionInsights'; -///: END:ONLY_INCLUDE_IN(flask) +///: END:ONLY_INCLUDE_IN import { getAccountName, getAddressBookEntry, getIsBuyableChain, getMetadataContractName, getMetaMaskIdentities, + getMetaMetricsId, getNetworkIdentifier, getSwapsDefaultToken, } from '../../../selectors'; @@ -116,6 +119,8 @@ const ConfirmPageContainer = (props) => { getMetadataContractName(state, toAddress), ); + const metaMetricsId = useSelector(getMetaMetricsId); + // TODO: Move useRamps hook to the confirm-transaction-base parent component. // TODO: openBuyCryptoInPdapp should be passed to this component as a custom prop. // We try to keep this component for layout purpose only, we need to move this hook to the confirm-transaction-base parent @@ -140,7 +145,7 @@ const ConfirmPageContainer = (props) => { setCollectionBalance(tokenBalance?.balance?.words?.[0] || 0); }, [fromAddress, tokenAddress]); - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) // As confirm-transction-base is converted to functional component // this code can bemoved to it. const insightComponent = useTransactionInsights({ @@ -198,6 +203,7 @@ const ConfirmPageContainer = (props) => { )} {contentComponent || ( { detailsComponent={detailsComponent} dataComponent={dataComponent} dataHexComponent={dataHexComponent} - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) insightComponent={insightComponent} ///: END:ONLY_INCLUDE_IN errorMessage={errorMessage} @@ -247,6 +253,7 @@ const ConfirmPageContainer = (props) => { {t('insufficientCurrencyBuyOrDeposit', [ nativeCurrency, networkName, + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) , + ///: END:ONLY_INCLUDE_IN ])} ) : ( diff --git a/ui/components/app/confirm-page-container/index.js b/ui/components/app/confirm-page-container/index.js index 011248f2f..5d2ea8039 100644 --- a/ui/components/app/confirm-page-container/index.js +++ b/ui/components/app/confirm-page-container/index.js @@ -7,6 +7,6 @@ export { default as ConfirmPageContainerContent, ConfirmPageContainerSummary, } from './confirm-page-container-content'; -///: BEGIN:ONLY_INCLUDE_IN(flask) -export { SnapInsight } from './flask/snap-insight'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +export { SnapInsight } from './snaps/snap-insight'; ///: END:ONLY_INCLUDE_IN diff --git a/ui/components/app/confirm-page-container/index.scss b/ui/components/app/confirm-page-container/index.scss index ca1ac9fb1..d3e8878f1 100644 --- a/ui/components/app/confirm-page-container/index.scss +++ b/ui/components/app/confirm-page-container/index.scss @@ -2,8 +2,8 @@ @import 'confirm-page-container-header/index'; @import 'confirm-detail-row/index'; @import 'confirm-page-container-navigation/index'; -///: BEGIN:ONLY_INCLUDE_IN(flask) -@import 'flask/index'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +@import 'snaps/index'; ///: END:ONLY_INCLUDE_IN .confirm-page-container { diff --git a/ui/components/app/confirm-page-container/flask/index.js b/ui/components/app/confirm-page-container/snaps/index.js similarity index 100% rename from ui/components/app/confirm-page-container/flask/index.js rename to ui/components/app/confirm-page-container/snaps/index.js diff --git a/ui/components/app/confirm-page-container/flask/index.scss b/ui/components/app/confirm-page-container/snaps/index.scss similarity index 100% rename from ui/components/app/confirm-page-container/flask/index.scss rename to ui/components/app/confirm-page-container/snaps/index.scss diff --git a/ui/components/app/confirm-page-container/flask/snap-insight.js b/ui/components/app/confirm-page-container/snaps/snap-insight.js similarity index 90% rename from ui/components/app/confirm-page-container/flask/snap-insight.js rename to ui/components/app/confirm-page-container/snaps/snap-insight.js index 13d182736..703bcff67 100644 --- a/ui/components/app/confirm-page-container/flask/snap-insight.js +++ b/ui/components/app/confirm-page-container/snaps/snap-insight.js @@ -13,13 +13,13 @@ import { TextVariant, } from '../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { useTransactionInsightSnap } from '../../../../hooks/flask/useTransactionInsightSnap'; +import { useTransactionInsightSnap } from '../../../../hooks/snaps/useTransactionInsightSnap'; import Box from '../../../ui/box/box'; -import { SnapUIRenderer } from '../../flask/snap-ui-renderer'; -import { SnapDelineator } from '../../flask/snap-delineator'; -import { DelineatorType } from '../../../../helpers/constants/flask'; +import { SnapUIRenderer } from '../../snaps/snap-ui-renderer'; +import { SnapDelineator } from '../../snaps/snap-delineator'; +import { DelineatorType } from '../../../../helpers/constants/snaps'; import { getSnapName } from '../../../../helpers/utils/util'; -import { Copyable } from '../../flask/copyable'; +import { Copyable } from '../../snaps/copyable'; import { getTargetSubjectMetadata } from '../../../../selectors'; export const SnapInsight = ({ transaction, origin, chainId, selectedSnap }) => { diff --git a/ui/components/app/confirm-subtitle/confirm-subtitle.test.js b/ui/components/app/confirm-subtitle/confirm-subtitle.test.js index 41cdc3da4..b8218029a 100644 --- a/ui/components/app/confirm-subtitle/confirm-subtitle.test.js +++ b/ui/components/app/confirm-subtitle/confirm-subtitle.test.js @@ -46,7 +46,7 @@ describe('ConfirmSubTitle', () => { mockState.metamask.preferences.showFiatInTestnets = false; mockState.metamask.allNftContracts = { [mockState.metamask.selectedAddress]: { - [hexToDecimal(mockState.metamask.provider.chainId)]: [ + [hexToDecimal(mockState.metamask.providerConfig.chainId)]: [ { address: '0x9' }, ], }, diff --git a/ui/components/app/connected-status-indicator/connected-status-indicator.js b/ui/components/app/connected-status-indicator/connected-status-indicator.js index 55a268510..6274c7239 100644 --- a/ui/components/app/connected-status-indicator/connected-status-indicator.js +++ b/ui/components/app/connected-status-indicator/connected-status-indicator.js @@ -62,20 +62,22 @@ export default function ConnectedStatusIndicator({ onClick }) { ? t('tooltipSatusConnected') : t('tooltipSatusNotConnected'); return ( - )} - + ); } diff --git a/ui/components/app/contact-list/contact-list.test.js b/ui/components/app/contact-list/contact-list.test.js index fd03336e8..fce0619ae 100644 --- a/ui/components/app/contact-list/contact-list.test.js +++ b/ui/components/app/contact-list/contact-list.test.js @@ -6,7 +6,7 @@ import ContactList from '.'; describe('Contact List', () => { const store = configureMockStore([])({ - metamask: { provider: { chainId: '0x0' } }, + metamask: { providerConfig: { chainId: '0x0' } }, }); describe('given searchForContacts', () => { diff --git a/ui/components/app/currency-input/currency-input.test.js b/ui/components/app/currency-input/currency-input.test.js index a870cfe99..91ab46b71 100644 --- a/ui/components/app/currency-input/currency-input.test.js +++ b/ui/components/app/currency-input/currency-input.test.js @@ -10,7 +10,7 @@ describe('CurrencyInput Component', () => { nativeCurrency: 'ETH', currentCurrency: 'usd', conversionRate: 231.06, - provider: { + providerConfig: { chainId: '0x5', }, preferences: { diff --git a/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap b/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap index d72f4736d..a62361e35 100644 --- a/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap +++ b/ui/components/app/custom-spending-cap/__snapshots__/custom-spending-cap.test.js.snap @@ -24,7 +24,9 @@ exports[`CustomSpendingCap should match snapshot 1`] = ` class="box form-field__heading-title box--display-flex box--flex-direction-row box--align-items-baseline" >
Custom spending cap
diff --git a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js index 49aebd8e4..1c68eb297 100644 --- a/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js +++ b/ui/components/app/custom-spending-cap/custom-spending-cap-tooltip.js @@ -1,14 +1,14 @@ import React from 'react'; import PropTypes from 'prop-types'; import Box from '../../ui/box'; -import Typography from '../../ui/typography'; import Tooltip from '../../ui/tooltip'; import { TextColor, DISPLAY, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; -import { Icon, IconName, IconSize } from '../../component-library'; + +import { Icon, IconName, IconSize, Text } from '../../component-library'; export const CustomSpendingCapTooltip = ({ tooltipContentText, @@ -19,21 +19,22 @@ export const CustomSpendingCapTooltip = ({ interactive position="top" html={ - {tooltipContentText} - + } > {tooltipIcon ? ( ) : ( diff --git a/ui/components/app/detected-token/detected-token-address/detected-token-address.js b/ui/components/app/detected-token/detected-token-address/detected-token-address.js index 9ae894aaf..2e752bce1 100644 --- a/ui/components/app/detected-token/detected-token-address/detected-token-address.js +++ b/ui/components/app/detected-token/detected-token-address/detected-token-address.js @@ -6,16 +6,16 @@ import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; import Box from '../../../ui/box'; import Button from '../../../ui/button'; -import Typography from '../../../ui/typography'; import Tooltip from '../../../ui/tooltip'; import { DISPLAY, TextColor, - TypographyVariant, + TextVariant, } from '../../../../helpers/constants/design-system'; import { shortenAddress } from '../../../../helpers/utils/util'; +import { Text } from '../../../component-library'; const DetectedTokenAddress = ({ tokenAddress }) => { const t = useI18nContext(); @@ -23,17 +23,18 @@ const DetectedTokenAddress = ({ tokenAddress }) => { return ( - + {`${t('tokenAddress')}:`} - - + {shortenAddress(tokenAddress)} - + { return ( - + {t('fromTokenLists', [ numOfHiddenAggregators > 0 && !displayMore ? ( - {`${aggregators @@ -44,18 +42,19 @@ const DetectedTokenAggregators = ({ aggregators }) => { > {t('plusXMore', [numOfHiddenAggregators])} - + ) : ( - {`${aggregators.join(', ')}.`} - + ), ])} - + ); }; diff --git a/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js b/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js index 2a2566109..708b078db 100644 --- a/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js +++ b/ui/components/app/detected-token/detected-token-ignored-popover/detected-token-ignored-popover.js @@ -5,8 +5,8 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import Popover from '../../../ui/popover'; import Button from '../../../ui/button'; -import Typography from '../../../ui/typography/typography'; -import { TypographyVariant } from '../../../../helpers/constants/design-system'; +import { TextVariant } from '../../../../helpers/constants/design-system'; +import { Text } from '../../../component-library'; const DetectedTokenIgnoredPopover = ({ partiallyIgnoreDetectedTokens, @@ -48,9 +48,9 @@ const DetectedTokenIgnoredPopover = ({ })} footer={footer} > - + ); }; diff --git a/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js b/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js index 0f80fea92..65fa8d0b3 100644 --- a/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js +++ b/ui/components/app/detected-token/detected-token-selection-popover/detected-token-selection-popover.js @@ -9,7 +9,10 @@ import { MetaMetricsEventName, MetaMetricsTokenEventSource, } from '../../../../../shared/constants/metametrics'; -import { getDetectedTokensInCurrentNetwork } from '../../../../selectors'; +import { + getCurrentChainId, + getDetectedTokensInCurrentNetwork, +} from '../../../../selectors'; import Popover from '../../../ui/popover'; import Box from '../../../ui/box'; @@ -27,6 +30,8 @@ const DetectedTokenSelectionPopover = ({ const t = useI18nContext(); const trackEvent = useContext(MetaMetricsContext); + const chainId = useSelector(getCurrentChainId); + const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork); const { selected: selectedTokens = [] } = sortingBasedOnTokenSelection(tokensListDetected); @@ -44,7 +49,8 @@ const DetectedTokenSelectionPopover = ({ event: MetaMetricsEventName.TokenImportCanceled, category: MetaMetricsEventCategory.Wallet, properties: { - source: MetaMetricsTokenEventSource.Detected, + source_connection_method: MetaMetricsTokenEventSource.Detected, + chain_id: chainId, tokens: eventTokensDetails, }, }); diff --git a/ui/components/app/detected-token/detected-token-values/detected-token-values.js b/ui/components/app/detected-token/detected-token-values/detected-token-values.js index 37dcfbad4..67d16c946 100644 --- a/ui/components/app/detected-token/detected-token-values/detected-token-values.js +++ b/ui/components/app/detected-token/detected-token-values/detected-token-values.js @@ -3,17 +3,17 @@ import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import Box from '../../../ui/box'; -import Typography from '../../../ui/typography'; import CheckBox from '../../../ui/check-box'; import { DISPLAY, TextColor, - TypographyVariant, + TextVariant, } from '../../../../helpers/constants/design-system'; import { useTokenTracker } from '../../../../hooks/useTokenTracker'; import { useTokenFiatAmount } from '../../../../hooks/useTokenFiatAmount'; import { getUseCurrencyRateCheck } from '../../../../selectors'; +import { Text } from '../../../component-library'; const DetectedTokenValues = ({ token, @@ -46,17 +46,18 @@ const DetectedTokenValues = ({ return ( - + {`${balanceString || '0'} ${token.symbol}`} - - + {useCurrencyRateCheck ? formattedFiatBalance || '$0' // since formattedFiatBalance will be when teh conversion rate is not obtained, should be replace the `$0` with `N/A` : formattedFiatBalance} - + diff --git a/ui/components/app/detected-token/detected-token.js b/ui/components/app/detected-token/detected-token.js index 02484563b..e9deaea9c 100644 --- a/ui/components/app/detected-token/detected-token.js +++ b/ui/components/app/detected-token/detected-token.js @@ -8,7 +8,10 @@ import { ignoreTokens, setNewTokensImported, } from '../../../store/actions'; -import { getDetectedTokensInCurrentNetwork } from '../../../selectors'; +import { + getCurrentChainId, + getDetectedTokensInCurrentNetwork, +} from '../../../selectors'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { @@ -47,6 +50,7 @@ const DetectedToken = ({ setShowDetectedTokens }) => { const dispatch = useDispatch(); const trackEvent = useContext(MetaMetricsContext); + const chainId = useSelector(getCurrentChainId); const detectedTokens = useSelector(getDetectedTokensInCurrentNetwork); const [tokensListDetected, setTokensListDetected] = useState(() => @@ -69,9 +73,11 @@ const DetectedToken = ({ setShowDetectedTokens }) => { token_symbol: importedToken.symbol, token_contract_address: importedToken.address, token_decimal_precision: importedToken.decimals, - source: MetaMetricsTokenEventSource.Detected, + source_connection_method: MetaMetricsTokenEventSource.Detected, token_standard: TokenStandard.ERC20, asset_type: AssetType.token, + token_added_type: 'detected', + chain_id: chainId, }, }); }); diff --git a/ui/components/app/dropdowns/network-dropdown.js b/ui/components/app/dropdowns/network-dropdown.js index 8b44fed0e..3c1ceb8e2 100644 --- a/ui/components/app/dropdowns/network-dropdown.js +++ b/ui/components/app/dropdowns/network-dropdown.js @@ -7,6 +7,7 @@ import { pickBy } from 'lodash'; import Button from '../../ui/button'; import * as actions from '../../../store/actions'; import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network'; +import { getProviderConfig } from '../../../ducks/metamask/metamask'; import { BUILT_IN_NETWORKS, CHAIN_ID_TO_RPC_URL_MAP, @@ -55,7 +56,7 @@ const DROP_DOWN_MENU_ITEM_STYLE = { function mapStateToProps(state) { return { - provider: state.metamask.provider, + providerConfig: getProviderConfig(state), shouldShowTestNetworks: getShowTestNetworks(state), networkConfigurations: state.metamask.networkConfigurations, networkDropdownOpen: state.appState.networkDropdownOpen, @@ -97,7 +98,7 @@ class NetworkDropdown extends Component { }; static propTypes = { - provider: PropTypes.shape({ + providerConfig: PropTypes.shape({ nickname: PropTypes.string, rpcUrl: PropTypes.string, type: PropTypes.string, @@ -122,7 +123,7 @@ class NetworkDropdown extends Component { handleClick(newProviderType) { const { - provider: { type: providerType }, + providerConfig: { type: providerType }, setProviderType, } = this.props; const { trackEvent } = this.context; @@ -163,12 +164,13 @@ class NetworkDropdown extends Component { ); } - renderCustomRpcList(networkConfigurations, provider, opts = {}) { + renderCustomRpcList(networkConfigurations, providerConfig, opts = {}) { return Object.entries(networkConfigurations).map( ([networkConfigurationId, networkConfiguration]) => { const { rpcUrl, chainId, nickname = '', id } = networkConfiguration; const isCurrentRpcTarget = - provider.type === NETWORK_TYPES.RPC && rpcUrl === provider.rpcUrl; + providerConfig.type === NETWORK_TYPES.RPC && + rpcUrl === providerConfig.rpcUrl; return ( diff --git a/ui/components/app/dropdowns/network-dropdown.test.js b/ui/components/app/dropdowns/network-dropdown.test.js index a4a1f6398..a54807e41 100644 --- a/ui/components/app/dropdowns/network-dropdown.test.js +++ b/ui/components/app/dropdowns/network-dropdown.test.js @@ -23,7 +23,7 @@ describe('Network Dropdown', () => { metamask: { networkId: '1', networkStatus: 'available', - provider: { + providerConfig: { type: 'test', }, showTestnetMessageInDropdown: false, @@ -58,7 +58,7 @@ describe('Network Dropdown', () => { metamask: { networkId: '1', networkStatus: 'available', - provider: { + providerConfig: { type: 'test', }, showTestnetMessageInDropdown: false, @@ -137,7 +137,7 @@ describe('Network Dropdown', () => { metamask: { networkId: '1', networkStatus: 'available', - provider: { + providerConfig: { type: 'test', }, showTestnetMessageInDropdown: false, diff --git a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js index e3ee7fa00..70fb157e1 100644 --- a/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js +++ b/ui/components/app/edit-gas-fee-button/edit-gas-fee-button.js @@ -5,7 +5,7 @@ import { EditGasModes, PriorityLevels } from '../../../../shared/constants/gas'; import { Color, TextColor, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; import { PRIORITY_LEVEL_ICON_MAP } from '../../../helpers/constants/gas'; import { useGasFeeContext } from '../../../contexts/gasFee'; @@ -13,8 +13,7 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { useTransactionEventFragment } from '../../../hooks/useTransactionEventFragment'; import { useTransactionModalContext } from '../../../contexts/transaction-modal'; import InfoTooltip from '../../ui/info-tooltip/info-tooltip'; -import Typography from '../../ui/typography/typography'; -import { Icon, IconName, IconSize } from '../../component-library'; +import { Icon, IconName, IconSize, Text } from '../../component-library'; export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { const t = useI18nContext(); @@ -87,22 +86,23 @@ export default function EditGasFeeButton({ userAcknowledgedGasMissing }) { contentText={
{transaction?.origin && ( - {t('dappSuggestedTooltip', [transaction.origin])} - + )} - + {t('maxBaseFee')} {maxFeePerGas} - - + + {t('maxPriorityFee')} {maxPriorityFeePerGas} - - + + {t('gasLimit')} {gasLimit} - +
} position="top" diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js index 935bf4e2b..d057f042b 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.js @@ -6,16 +6,16 @@ import { useTransactionModalContext } from '../../../contexts/transaction-modal' import Box from '../../ui/box'; import ErrorMessage from '../../ui/error-message'; import Popover from '../../ui/popover'; -import Typography from '../../ui/typography/typography'; import { TextColor, - TypographyVariant, + TextVariant, } from '../../../helpers/constants/design-system'; import { INSUFFICIENT_FUNDS_ERROR_KEY } from '../../../helpers/constants/error-keys'; import { useGasFeeContext } from '../../../contexts/gasFee'; import AppLoadingSpinner from '../app-loading-spinner'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; +import { Text } from '../../component-library'; import EditGasItem from './edit-gas-item'; import NetworkStatistics from './network-statistics'; @@ -84,12 +84,13 @@ const EditGasFeePopover = () => {
- {t('learnMoreAboutGas', [ { {t('learnMore')} , ])} - +
diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.test.js b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.test.js index 5fec41f57..3e371a05d 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.test.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-fee-popover.test.js @@ -53,7 +53,7 @@ const render = ({ txProps, contextProps } = {}) => { const store = configureStore({ metamask: { nativeCurrency: ETH, - provider: {}, + providerConfig: {}, cachedBalances: {}, accounts: { '0xAddress': { diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.test.js b/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.test.js index 653b23d8a..44ac34b87 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.test.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-item/edit-gas-item.test.js @@ -59,7 +59,7 @@ const renderComponent = ({ const store = configureStore({ metamask: { nativeCurrency: ETH, - provider: {}, + providerConfig: {}, cachedBalances: {}, accounts: { '0xAddress': { diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js index 685354471..2d700e3c7 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.js @@ -5,13 +5,13 @@ import { PriorityLevels, } from '../../../../../shared/constants/gas'; import { - FONT_WEIGHT, + FontWeight, TextColor, - TypographyVariant, + TextVariant, } from '../../../../helpers/constants/design-system'; import { isMetamaskSuggestedGasEstimate } from '../../../../helpers/utils/gas'; import { roundToDecimalPlacesRemovingExtraZeroes } from '../../../../helpers/utils/util'; -import Typography from '../../../ui/typography'; +import { Text } from '../../../component-library'; const EditGasToolTip = ({ editGasMode, @@ -107,43 +107,47 @@ const EditGasToolTip = ({ ) : null} {toolTipMessage && (
- + {toolTipMessage} - +
)} {priorityLevel === PriorityLevels.custom || estimateGreaterThanGasUse ? null : (
- {t('maxBaseFee')} - + {maxFeePerGas && ( - {roundToDecimalPlacesRemovingExtraZeroes(maxFeePerGas, 4)} - + )}
- {t('priorityFeeProperCase')} - + {maxPriorityFeePerGas && ( - @@ -151,25 +155,27 @@ const EditGasToolTip = ({ maxPriorityFeePerGas, 4, )} - + )}
- {t('gasLimit')} - + {gasLimit && ( - {roundToDecimalPlacesRemovingExtraZeroes(gasLimit, 4)} - + )}
diff --git a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.test.js b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.test.js index 6c9adbadb..dbeda43ac 100644 --- a/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.test.js +++ b/ui/components/app/edit-gas-fee-popover/edit-gas-tooltip/edit-gas-tooltip.test.js @@ -33,7 +33,7 @@ const HIGH_GAS_OPTION = { const renderComponent = (componentProps) => { const mockStore = { metamask: { - provider: {}, + providerConfig: {}, cachedBalances: {}, accounts: { '0xAddress': { diff --git a/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js b/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js index 43baa0606..6a14f655b 100644 --- a/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js +++ b/ui/components/app/edit-gas-fee-popover/network-statistics/network-statistics.js @@ -1,14 +1,14 @@ import React, { useContext } from 'react'; import { - FONT_WEIGHT, + FontWeight, TextColor, - TypographyVariant, + TextVariant, } from '../../../../helpers/constants/design-system'; import { isNullish } from '../../../../helpers/utils/util'; import { formatGasFeeOrFeeRange } from '../../../../helpers/utils/gas'; import { I18nContext } from '../../../../contexts/i18n'; import { useGasFeeContext } from '../../../../contexts/gasFee'; -import Typography from '../../../ui/typography/typography'; +import { Text } from '../../../component-library'; import { BaseFeeTooltip, PriorityFeeTooltip } from './tooltips'; import StatusSlider from './status-slider'; @@ -29,15 +29,16 @@ const NetworkStatistics = () => { return (
- {t('networkStatus')} - +
{isNullish(formattedLatestBaseFee) ? null : (
{ - // We're using optional chaining with snapId, because with the current implementation - // of snap update in the snap controller, we do not have reference to snapId when an - // update request is rejected because the reference comes from the request itself and not subject metadata - // like it is done with snap install - const snapPrefix = snapId && getSnapPrefix(snapId); - const packageName = snapId && removeSnapIdPrefix(snapId); - const isNPM = snapPrefix === 'npm:'; - const url = isNPM - ? `https://www.npmjs.com/package/${packageName}` - : packageName; - - const subjectMetadata = useSelector((state) => - getTargetSubjectMetadata(state, snapId), - ); - - const friendlyName = snapId && getSnapName(snapId, subjectMetadata); - - return ( - - - - - - {friendlyName} - - {packageName} - - - - - ); -}; - -SnapAuthorship.propTypes = { - /** - * The id of the snap - */ - snapId: PropTypes.string, - /** - * The className of the SnapAuthorship - */ - className: PropTypes.string, -}; - -export default SnapAuthorship; diff --git a/ui/components/app/flask/snap-settings-card/index.scss b/ui/components/app/flask/snap-settings-card/index.scss deleted file mode 100644 index 728a2e62c..000000000 --- a/ui/components/app/flask/snap-settings-card/index.scss +++ /dev/null @@ -1,57 +0,0 @@ -$version-max-width: 56px; // Increase to show more of the version number -$body-line-clamp: 4; // Number of lines in card body before truncating - -.snap-settings-card { - &__title { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - &__toggle-container { - margin-left: auto; - - &__toggle-button { - margin-right: -12px; // react-toggle-button width fix - } - } - - &__body { - overflow: hidden; - /* stylelint-disable */ - display: -webkit-box; - -webkit-line-clamp: $body-line-clamp; - -webkit-box-orient: vertical; - /* stylelint-enable */ - } - - &__version.box { - margin-left: auto; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: $version-max-width; - flex: 0 0 $version-max-width; - text-align: right; - } - - &__chip.chip { - margin: 0; - margin-left: auto; - display: inline-flex; - align-items: center; - text-transform: capitalize; - } - - &__button.button { - padding: 4px 16px; - display: inline-flex; - align-items: center; - } - - &__date-added { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } -} diff --git a/ui/components/app/flask/snap-settings-card/snap-settings-card.js b/ui/components/app/flask/snap-settings-card/snap-settings-card.js deleted file mode 100644 index 709a7bc6d..000000000 --- a/ui/components/app/flask/snap-settings-card/snap-settings-card.js +++ /dev/null @@ -1,258 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; - -import { useI18nContext } from '../../../../hooks/useI18nContext'; - -import Card from '../../../ui/card'; -import Box from '../../../ui/box'; -import IconWithFallback from '../../../ui/icon-with-fallback'; -import IconBorder from '../../../ui/icon-border'; -import Typography from '../../../ui/typography/typography'; -import ToggleButton from '../../../ui/toggle-button'; -import Chip from '../../../ui/chip'; -import ColorIndicator from '../../../ui/color-indicator'; -import Button from '../../../ui/button'; -import Tooltip from '../../../ui/tooltip'; - -import { - Color, - TypographyVariant, - FONT_WEIGHT, - AlignItems, - JustifyContent, - DISPLAY, - TEXT_ALIGN, - TextColor, - BackgroundColor, -} from '../../../../helpers/constants/design-system'; - -const STATUSES = { - INSTALLING: 'installing', - RUNNING: 'running', - STOPPED: 'stopped', - CRASHED: 'crashed', -}; - -const STATUS_COLORS = { - [STATUSES.INSTALLING]: Color.warningDefault, - [STATUSES.RUNNING]: Color.successDefault, - [STATUSES.STOPPED]: Color.infoMuted, - [STATUSES.CRASHED]: Color.errorDefault, -}; - -const SnapSettingsCard = ({ - name, - description, - icon, - dateAdded = '', - version, - url, - onToggle, - isEnabled = false, - onClick, - status, - className, - cardProps, - toggleButtonProps, - buttonProps, - chipProps, -}) => { - const t = useI18nContext(); - - return ( - - - {(icon || name) && ( - - - - - - )} - - {name} - - - - - - - - - {description} - - - - - - - - - - - - } - label={status} - labelProps={{ - color: Color.textAlternative, - margin: [0, 1], - }} - backgroundColor={BackgroundColor.backgroundAlternative} - className="snap-settings-card__chip" - {...chipProps} - /> - - - - - {(dateAdded || version) && ( - <> - - {`${ - dateAdded && t('flaskSnapSettingsCardDateAddedOn') - } ${dateAdded} ${url && t('flaskSnapSettingsCardFrom')} ${url}`} - - - {t('shorthandVersion', [version])} - - - )} - - - - ); -}; - -SnapSettingsCard.propTypes = { - /** - * Name of the snap used for the title of the card and fallback letter for the snap icon - */ - name: PropTypes.string, - /** - * Description of the snap. Truncates after 4 lines - */ - description: PropTypes.string, - /** - * Image source of the snap icon for the IconWithFallback component - */ - icon: PropTypes.string, - /** - * Date the snap was added. Date will need formatting - */ - dateAdded: PropTypes.string, - /** - * The version of the snap in semver. Will truncate after 4 numbers e.g. 10.5.1... - */ - version: PropTypes.string, - /** - * Url of the snap website - */ - url: PropTypes.string, - /** - * The onChange function for the ToggleButton component - */ - onToggle: PropTypes.func, - /** - * Whether the snap is enabled. `value` prop of the ToggleButton - */ - isEnabled: PropTypes.bool, - /** - * onClick function of the "See Details" Button - */ - onClick: PropTypes.func, - /** - * Status of the snap must be one - */ - status: PropTypes.oneOf(Object.values(STATUSES)).isRequired, - /** - * Additional className added to the root div of the SnapSettingsCard component - */ - className: PropTypes.string, - /** - * Optional additional props passed to the Card component - */ - cardProps: PropTypes.shape(Card.propTypes), - /** - * Optional additional props passed to the ToggleButton component - */ - toggleButtonProps: PropTypes.shape(ToggleButton.propTypes), - /** - * Optional additional props passed to the Button component - */ - buttonProps: PropTypes.shape(Button.propTypes), - /** - * Optional additional props passed to the Chip component - */ - chipProps: PropTypes.shape(Chip.propTypes), -}; - -export default SnapSettingsCard; diff --git a/ui/components/app/flask/snap-settings-card/snap-settings-card.test.js b/ui/components/app/flask/snap-settings-card/snap-settings-card.test.js deleted file mode 100644 index 9a09e4da9..000000000 --- a/ui/components/app/flask/snap-settings-card/snap-settings-card.test.js +++ /dev/null @@ -1,76 +0,0 @@ -import * as React from 'react'; -import { render, fireEvent } from '@testing-library/react'; -import SnapSettingsCard from '.'; - -describe('SnapSettingsCard', () => { - const args = { - name: 'Snap name', - description: - 'This snap provides developers everywhere access to an entirely new data storage paradigm, even letting your programs store data autonomously.', - dateAdded: new Date().toDateString(), - version: '10.5.1234', - url: 'https://metamask.io', - status: 'stopped', - icon: './AST.png', - }; - it('should render the SnapsSettingCard without crashing', () => { - const { getByText } = render(); - expect(getByText('Snap name')).toBeDefined(); - }); - - it('should render the pill as installing when given a status of installing', () => { - args.status = 'installing'; - const { getByText } = render(); - expect(getByText('installing')).toBeDefined(); - }); - - it('should render the pill as running when given a status of running', () => { - args.status = 'running'; - const { getByText } = render(); - expect(getByText('running')).toBeDefined(); - }); - - it('should render the pill as installing when given a status of stopped', () => { - args.status = 'stopped'; - const { getByText } = render(); - expect(getByText('stopped')).toBeDefined(); - }); - - it('should render the pill as crashed when given a status of crashed', () => { - args.status = 'crashed'; - const { getByText } = render(); - expect(getByText('crashed')).toBeDefined(); - }); - - it('should call onToggle prop when toggle button is clicked', () => { - const onToggle = jest.fn(); - args.onToggle = onToggle; - const { container } = render(); - const toggleBtn = container.querySelector('.toggle-button').firstChild; - fireEvent.click(toggleBtn); - expect(onToggle).toHaveBeenCalled(); - }); - - it('should call onClick prop when See Details button is clicked', () => { - const onClick = jest.fn(); - args.onClick = onClick; - const { container } = render(); - const seeDetailsBtn = container.querySelector( - '.snap-settings-card__button', - ); - fireEvent.click(seeDetailsBtn); - expect(onClick).toHaveBeenCalled(); - }); - - it('should render an icon image', () => { - const { getByAltText } = render(); - const image = getByAltText(args.name); - expect(image).toBeDefined(); - expect(image).toHaveAttribute('src', args.icon); - }); - - it('should render the icon fallback using the first letter of the name', () => { - const { getByText } = render(); - expect(getByText('S')).toBeDefined(); - }); -}); diff --git a/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.test.js b/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.test.js index 809932567..9d8f36c4e 100644 --- a/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.test.js +++ b/ui/components/app/gas-details-item/gas-details-item-title/gas-details-item-title.test.js @@ -20,7 +20,7 @@ jest.mock('../../../../store/actions', () => ({ const render = () => { const store = configureStore({ metamask: { - provider: { chainId: CHAIN_IDS.MAINNET }, + providerConfig: { chainId: CHAIN_IDS.MAINNET }, cachedBalances: {}, accounts: { '0xAddress': { diff --git a/ui/components/app/gas-details-item/gas-details-item.js b/ui/components/app/gas-details-item/gas-details-item.js index 98550d17c..08a021451 100644 --- a/ui/components/app/gas-details-item/gas-details-item.js +++ b/ui/components/app/gas-details-item/gas-details-item.js @@ -52,7 +52,7 @@ const GasDetailsItem = ({ userAcknowledgedGasMissing = false }) => { return ( } detailTitleColor={TextColor.textDefault} detailText={ diff --git a/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.js b/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.js index c08df6016..fe2b422d4 100644 --- a/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.js +++ b/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.js @@ -9,6 +9,12 @@ import { DISPLAY, JustifyContent, } from '../../../helpers/constants/design-system'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + MetaMetricsEventCategory, + MetaMetricsEventKeyType, + MetaMetricsEventName, +} from '../../../../shared/constants/metametrics'; const radius = 14; const strokeWidth = 2; @@ -19,6 +25,7 @@ export default function HoldToRevealButton({ buttonText, onLongPressed }) { const isLongPressing = useRef(false); const [isUnlocking, setIsUnlocking] = useState(false); const [hasTriggeredUnlock, setHasTriggeredUnlock] = useState(false); + const trackEvent = useContext(MetaMetricsContext); /** * Prevent animation events from propogating up @@ -34,6 +41,13 @@ export default function HoldToRevealButton({ buttonText, onLongPressed }) { */ const onMouseDown = () => { isLongPressing.current = true; + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpHoldToRevealClickStarted, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); }; /** @@ -57,6 +71,20 @@ export default function HoldToRevealButton({ buttonText, onLongPressed }) { */ const triggerOnLongPressed = useCallback( (e) => { + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpHoldToRevealCompleted, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpRevealViewed, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); onLongPressed(); setHasTriggeredUnlock(true); preventPropogation(e); @@ -93,6 +121,7 @@ export default function HoldToRevealButton({ buttonText, onLongPressed }) {
diff --git a/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.test.js b/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.test.js index f3f7c4d97..16c6c0917 100644 --- a/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.test.js +++ b/ui/components/app/hold-to-reveal-button/hold-to-reveal-button.test.js @@ -1,7 +1,19 @@ import React from 'react'; import { render, fireEvent, waitFor } from '@testing-library/react'; +import { + MetaMetricsEventCategory, + MetaMetricsEventKeyType, + MetaMetricsEventName, +} from '../../../../shared/constants/metametrics'; import HoldToRevealButton from './hold-to-reveal-button'; +const mockTrackEvent = jest.fn(); + +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useContext: () => mockTrackEvent, +})); + describe('HoldToRevealButton', () => { let props = {}; @@ -14,6 +26,10 @@ describe('HoldToRevealButton', () => { }; }); + afterEach(() => { + jest.resetAllMocks(); + }); + it('should render a button with label', () => { const { getByText } = render(); @@ -34,39 +50,66 @@ describe('HoldToRevealButton', () => { expect(button).toBeDefined(); }); - it('should not show the locked padlock when a button is long pressed and then should show it after it was lifted off before the animation concludes', () => { - const { getByText } = render(); + it('should show the locked padlock when a button is long pressed and then should show it after it was lifted off before the animation concludes', async () => { + const { getByText, queryByLabelText } = render( + , + ); const button = getByText('Hold to reveal SRP'); fireEvent.mouseDown(button); + const circleLocked = queryByLabelText('circle-locked'); - waitFor(() => { - expect(button.firstChild).toHaveClass( - 'hold-to-reveal-button__lock-icon-container', - ); + await waitFor(() => { + expect(circleLocked).toBeInTheDocument(); }); fireEvent.mouseUp(button); + const circleUnlocked = queryByLabelText('circle-unlocked'); - waitFor(() => { - expect(button.firstChild).not.toHaveClass( - 'hold-to-reveal-button__lock-icon-container', - ); + await waitFor(() => { + expect(circleUnlocked).not.toBeInTheDocument(); }); }); - it('should show the unlocked padlock when a button is long pressed for the duration of the animation', () => { - const { getByText } = render(); + it('should show the unlocked padlock when a button is long pressed for the duration of the animation', async () => { + const { getByText, queryByLabelText } = render( + , + ); const button = getByText('Hold to reveal SRP'); fireEvent.mouseDown(button); - waitFor(() => { - expect(button.firstChild).toHaveClass( - 'hold-to-reveal-button__unlock-icon-container', - ); + const circleLocked = queryByLabelText('circle-locked'); + fireEvent.transitionEnd(circleLocked); + + const circleUnlocked = queryByLabelText('circle-unlocked'); + fireEvent.animationEnd(circleUnlocked); + + await waitFor(() => { + expect(circleUnlocked).toBeInTheDocument(); + expect(mockTrackEvent).toHaveBeenNthCalledWith(2, { + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpHoldToRevealClickStarted, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + expect(mockTrackEvent).toHaveBeenNthCalledWith(5, { + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpHoldToRevealCompleted, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + expect(mockTrackEvent).toHaveBeenNthCalledWith(6, { + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpRevealViewed, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); }); }); }); diff --git a/ui/components/app/import-token-link/import-token-link.test.js b/ui/components/app/import-token-link/import-token-link.test.js index 551858532..504ab5ce3 100644 --- a/ui/components/app/import-token-link/import-token-link.test.js +++ b/ui/components/app/import-token-link/import-token-link.test.js @@ -26,7 +26,7 @@ describe('Import Token Link', () => { it('should match snapshot for goerli chainId', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x5', }, }, @@ -42,7 +42,7 @@ describe('Import Token Link', () => { it('should match snapshot for mainnet chainId', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x1', }, }, @@ -58,7 +58,7 @@ describe('Import Token Link', () => { it('should detectNewTokens when clicking refresh', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x5', }, }, @@ -77,7 +77,7 @@ describe('Import Token Link', () => { it('should push import token route', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x5', }, }, diff --git a/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap b/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap new file mode 100644 index 000000000..4dc118b20 --- /dev/null +++ b/ui/components/app/ledger-instruction-field/__snapshots__/ledger-instruction-field.test.js.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LedgerInstructionField Component rendering should render properly with data instruction 1`] = ` +
+
+
+
+ +
+
+
+ Prior to clicking confirm: +
+
+ • Be sure your Ledger is plugged in and to select the Ethereum app. +
+
+ • Enable "smart contract data" or "blind signing" on your Ledger device. +
+
+ + + +
+
+
+
+
+
+
+`; diff --git a/ui/components/app/ledger-instruction-field/ledger-instruction-field.js b/ui/components/app/ledger-instruction-field/ledger-instruction-field.js index 1552dd0a6..272c1aa59 100644 --- a/ui/components/app/ledger-instruction-field/ledger-instruction-field.js +++ b/ui/components/app/ledger-instruction-field/ledger-instruction-field.js @@ -19,15 +19,13 @@ import { getLedgerTransportStatus, } from '../../../ducks/app/app'; -import Typography from '../../ui/typography/typography'; -import Button from '../../ui/button'; +import { BannerAlert, ButtonLink, Text } from '../../component-library'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { - FONT_WEIGHT, + SEVERITIES, + TEXT_ALIGN, TextColor, - TypographyVariant, } from '../../../helpers/constants/design-system'; -import Dialog from '../../ui/dialog'; import { getPlatform, getEnvironmentType, @@ -42,14 +40,9 @@ const renderInstructionStep = ( ) => { return ( show && ( - + {text} - + ) ); }; @@ -71,8 +64,8 @@ export default function LedgerInstructionField({ showDataInstruction }) { ledgerTransportType === LedgerTransportTypes.webhid && webHidConnectedStatus !== WebHIDConnectedStatuses.connected ) { - const devices = await window.navigator.hid.getDevices(); - const webHidIsConnected = devices.some( + const devices = await window.navigator?.hid?.getDevices(); + const webHidIsConnected = devices?.some( (device) => device.vendorId === Number(LEDGER_USB_VENDOR_ID), ); dispatch( @@ -136,28 +129,28 @@ export default function LedgerInstructionField({ showDataInstruction }) { return (
- +
{renderInstructionStep(t('ledgerConnectionInstructionHeader'))} {renderInstructionStep( - `- ${t('ledgerConnectionInstructionStepOne')}`, + `• ${t('ledgerConnectionInstructionStepOne')}`, !isFirefox && usingLedgerLive, )} {renderInstructionStep( - `- ${t('ledgerConnectionInstructionStepTwo')}`, + `• ${t('ledgerConnectionInstructionStepTwo')}`, !isFirefox && usingLedgerLive, )} {renderInstructionStep( - `- ${t('ledgerConnectionInstructionStepThree')}`, + `• ${t('ledgerConnectionInstructionStepThree')}`, )} {renderInstructionStep( - `- ${t('ledgerConnectionInstructionStepFour')}`, + `• ${t('ledgerConnectionInstructionStepFour')}`, showDataInstruction, )} {renderInstructionStep( - + , transportStatus === HardwareTransportStates.deviceOpenFailure, )} {renderInstructionStep( - + , usingWebHID && webHidConnectedStatus === WebHIDConnectedStatuses.notConnected, TextColor.WARNING_DEFAULT, )}
-
+
); } LedgerInstructionField.propTypes = { + // whether or not to show the data instruction showDataInstruction: PropTypes.bool, }; diff --git a/ui/components/app/ledger-instruction-field/ledger-instruction-field.stories.js b/ui/components/app/ledger-instruction-field/ledger-instruction-field.stories.js new file mode 100644 index 000000000..44e4e0c0a --- /dev/null +++ b/ui/components/app/ledger-instruction-field/ledger-instruction-field.stories.js @@ -0,0 +1,17 @@ +import React from 'react'; +import LedgerInstructionField from '.'; + +export default { + title: 'Components/App/LedgerInstructionField', + argTypes: { + showDataInstruction: { + control: { + type: 'boolean', + }, + }, + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'Default'; diff --git a/ui/components/app/ledger-instruction-field/ledger-instruction-field.test.js b/ui/components/app/ledger-instruction-field/ledger-instruction-field.test.js new file mode 100644 index 000000000..7a523395c --- /dev/null +++ b/ui/components/app/ledger-instruction-field/ledger-instruction-field.test.js @@ -0,0 +1,28 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import LedgerInstructionField from '.'; + +describe('LedgerInstructionField Component', () => { + const mockStore = { + appState: { + ledgerWebHidConnectedStatus: 'notConnected', + }, + metamask: { + ledgerTransportType: 'webhid', + }, + }; + + describe('rendering', () => { + it('should render properly with data instruction', () => { + const store = configureMockStore()(mockStore); + + const { container } = renderWithProvider( + , + store, + ); + + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/ui/components/app/loading-network-screen/loading-network-screen.component.js b/ui/components/app/loading-network-screen/loading-network-screen.component.js index 9a258557d..72c4ea31e 100644 --- a/ui/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.component.js @@ -17,7 +17,7 @@ export default class LoadingNetworkScreen extends PureComponent { static propTypes = { loadingMessage: PropTypes.string, cancelTime: PropTypes.number, - provider: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + providerConfig: PropTypes.object, providerId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), showNetworkDropdown: PropTypes.func, setProviderArgs: PropTypes.array, @@ -38,8 +38,8 @@ export default class LoadingNetworkScreen extends PureComponent { if (loadingMessage) { return loadingMessage; } - const { provider, providerId } = this.props; - const providerName = provider.type; + const { providerConfig, providerId } = this.props; + const providerName = providerConfig.type; const { t } = this.context; switch (providerName) { @@ -125,9 +125,9 @@ export default class LoadingNetworkScreen extends PureComponent { }; componentDidUpdate = (prevProps) => { - const { provider } = this.props; - const { provider: prevProvider } = prevProps; - if (provider.type !== prevProvider.type) { + const { providerConfig } = this.props; + const { providerConfig: prevProvider } = prevProps; + if (providerConfig.type !== prevProvider.type) { window.clearTimeout(this.cancelCallTimeout); this.setState({ showErrorScreen: false }); this.cancelCallTimeout = setTimeout( diff --git a/ui/components/app/loading-network-screen/loading-network-screen.container.js b/ui/components/app/loading-network-screen/loading-network-screen.container.js index bb5a5d138..badf2b723 100644 --- a/ui/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.container.js @@ -2,32 +2,30 @@ import { connect } from 'react-redux'; import { NETWORK_TYPES } from '../../../../shared/constants/network'; import * as actions from '../../../store/actions'; import { getNetworkIdentifier, isNetworkLoading } from '../../../selectors'; +import { getProviderConfig } from '../../../ducks/metamask/metamask'; import LoadingNetworkScreen from './loading-network-screen.component'; const DEPRECATED_TEST_NET_CHAINIDS = ['0x3', '0x2a', '0x4']; const mapStateToProps = (state) => { const { loadingMessage } = state.appState; - const { provider } = state.metamask; - const { rpcUrl, chainId, ticker, nickname, type } = provider; + const providerConfig = getProviderConfig(state); + const { rpcUrl, chainId, ticker, nickname, type } = providerConfig; const setProviderArgs = - type === NETWORK_TYPES.RPC - ? [rpcUrl, chainId, ticker, nickname] - : [provider.type]; + type === NETWORK_TYPES.RPC ? [rpcUrl, chainId, ticker, nickname] : [type]; - const providerChainId = provider?.chainId; + const providerChainId = chainId; const isDeprecatedNetwork = DEPRECATED_TEST_NET_CHAINIDS.includes(providerChainId); - const isInfuraRpcUrl = - provider?.rpcUrl && new URL(provider.rpcUrl).host.endsWith('.infura.io'); + const isInfuraRpcUrl = rpcUrl && new URL(rpcUrl).host.endsWith('.infura.io'); const showDeprecatedRpcUrlWarning = isDeprecatedNetwork && isInfuraRpcUrl; return { isNetworkLoading: isNetworkLoading(state), loadingMessage, setProviderArgs, - provider, + providerConfig, providerId: getNetworkIdentifier(state), showDeprecatedRpcUrlWarning, }; diff --git a/ui/components/app/menu-bar/menu-bar.test.js b/ui/components/app/menu-bar/menu-bar.test.js index 2a148a54a..03db1f1ef 100644 --- a/ui/components/app/menu-bar/menu-bar.test.js +++ b/ui/components/app/menu-bar/menu-bar.test.js @@ -9,7 +9,7 @@ import MenuBar from './menu-bar'; const initState = { activeTab: {}, metamask: { - provider: { + providerConfig: { chainId: CHAIN_IDS.GOERLI, }, selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', diff --git a/ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js b/ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js index a1f782240..c494fae2b 100644 --- a/ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js +++ b/ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js @@ -1,5 +1,4 @@ import React from 'react'; -import { object } from '@storybook/addon-knobs'; import { TextColor, TypographyVariant, @@ -8,6 +7,12 @@ import MetaMaskTemplateRenderer from '.'; export default { title: 'Components/App/MetamaskTemplateRenderer', + component: MetaMaskTemplateRenderer, + argTypes: { + sections: { + control: 'object', + }, + }, }; const SECTIONS = { @@ -85,25 +90,12 @@ const SECTIONS = { ], }; -export const DefaultStory = () => ( - +export const DefaultStory = (args) => ( + ); DefaultStory.storyName = 'Default'; -export const WithInvalidElement = () => ( - -); +DefaultStory.args = { + sections: SECTIONS, +}; diff --git a/ui/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js index accd11841..d76f7298a 100644 --- a/ui/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/components/app/metamask-template-renderer/safe-component-list.js @@ -12,11 +12,11 @@ import TextField from '../../ui/text-field'; import ConfirmationNetworkSwitch from '../../../pages/confirmation/components/confirmation-network-switch'; import UrlIcon from '../../ui/url-icon'; import Tooltip from '../../ui/tooltip/tooltip'; -///: BEGIN:ONLY_INCLUDE_IN(flask) -import { SnapDelineator } from '../flask/snap-delineator'; -import { Copyable } from '../flask/copyable'; +///: BEGIN:ONLY_INCLUDE_IN(snaps) +import { SnapDelineator } from '../snaps/snap-delineator'; +import { Copyable } from '../snaps/copyable'; import Spinner from '../../ui/spinner'; -import { SnapUIMarkdown } from '../flask/snap-ui-markdown'; +import { SnapUIMarkdown } from '../snaps/snap-ui-markdown'; ///: END:ONLY_INCLUDE_IN export const safeComponentList = { @@ -40,7 +40,7 @@ export const safeComponentList = { TruncatedDefinitionList, Typography, UrlIcon, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(snaps) SnapDelineator, Copyable, Spinner, diff --git a/ui/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/components/app/modals/account-details-modal/account-details-modal.component.js index f1ad623c6..f35a8153b 100644 --- a/ui/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.component.js @@ -8,6 +8,10 @@ import EditableLabel from '../../../ui/editable-label'; import Button from '../../../ui/button'; import { getURLHostName } from '../../../../helpers/utils/util'; import { isHardwareKeyring } from '../../../../helpers/utils/hardware'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import CustodyLabels from '../../../institutional/custody-labels/custody-labels'; +import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +///: END:ONLY_INCLUDE_IN import { MetaMetricsEventCategory, MetaMetricsEventLinkType, @@ -28,6 +32,10 @@ export default class AccountDetailsModal extends Component { history: PropTypes.object, hideModal: PropTypes.func, blockExplorerLinkText: PropTypes.object, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + accountType: PropTypes.string, + custodyAccountDetails: PropTypes.object, + ///: END:ONLY_INCLUDE_IN }; static contextTypes = { @@ -46,6 +54,10 @@ export default class AccountDetailsModal extends Component { history, hideModal, blockExplorerLinkText, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + accountType, + custodyAccountDetails, + ///: END:ONLY_INCLUDE_IN } = this.props; const { name, address } = selectedIdentity; @@ -59,6 +71,17 @@ export default class AccountDetailsModal extends Component { exportPrivateKeyFeatureEnabled = false; } + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + if (keyring?.type?.search('Custody') !== -1) { + exportPrivateKeyFeatureEnabled = false; + } + const showCustodyLabels = accountType === 'custody'; + const custodyLabels = custodyAccountDetails + ? custodyAccountDetails[toChecksumHexAddress(selectedIdentity.address)] + ?.labels + : {}; + ///: END:ONLY_INCLUDE_IN + const routeToAddBlockExplorerUrl = () => { hideModal(); history.push(`${NETWORKS_ROUTE}#blockExplorerUrl`); @@ -88,7 +111,11 @@ export default class AccountDetailsModal extends Component { onSubmit={(label) => setAccountLabel(address, label)} accounts={this.props.accounts} /> - + { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + showCustodyLabels && + ///: END:ONLY_INCLUDE_IN + } { @@ -23,6 +29,10 @@ const mapStateToProps = (state) => { rpcPrefs: getRpcPrefsForCurrentProvider(state), accounts: getMetaMaskAccountsOrdered(state), blockExplorerLinkText: getBlockExplorerLinkText(state, true), + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + accountType: getAccountType(state), + custodyAccountDetails: getCustodyAccountDetails(state), + ///: END:ONLY_INCLUDE_IN }; }; diff --git a/ui/components/app/modals/account-details-modal/account-details-modal.test.js b/ui/components/app/modals/account-details-modal/account-details-modal.test.js index a66c4fc12..72bf233c2 100644 --- a/ui/components/app/modals/account-details-modal/account-details-modal.test.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.test.js @@ -86,7 +86,7 @@ describe('Account Details Modal', () => { }, }, }, - provider: { + providerConfig: { chainId: '0x99', }, }, diff --git a/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js index bfbf7a61d..31b225e53 100644 --- a/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js +++ b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js @@ -6,7 +6,7 @@ import CancelTransactionGasFee from './cancel-transaction-gas-fee.component'; describe('CancelTransactionGasFee Component', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x4', }, preferences: { diff --git a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js index 444188919..39e353565 100644 --- a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js +++ b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js @@ -7,7 +7,7 @@ import ConfirmRemoveAccount from '.'; describe('Confirm Remove Account', () => { const state = { metamask: { - provider: { + providerConfig: { chainId: '0x99', }, }, diff --git a/ui/components/app/modals/contract-details-modal/contract-details-modal.js b/ui/components/app/modals/contract-details-modal/contract-details-modal.js index 3316ff588..e6250a280 100644 --- a/ui/components/app/modals/contract-details-modal/contract-details-modal.js +++ b/ui/components/app/modals/contract-details-modal/contract-details-modal.js @@ -9,10 +9,9 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import Identicon from '../../../ui/identicon'; import { ellipsify } from '../../../../pages/send/send.utils'; import Popover from '../../../ui/popover'; -import Typography from '../../../ui/typography'; import { - FONT_WEIGHT, - TypographyVariant, + FontWeight, + TextVariant, DISPLAY, Size, BorderStyle, @@ -25,7 +24,7 @@ import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'; import { getAddressBookEntry } from '../../../../selectors'; import { TokenStandard } from '../../../../../shared/constants/transaction'; import NftCollectionImage from '../../../ui/nft-collection-image/nft-collection-image'; -import { ButtonIcon, IconName } from '../../../component-library'; +import { ButtonIcon, IconName, Text } from '../../../component-library'; export default function ContractDetailsModal({ onClose, @@ -62,32 +61,35 @@ export default function ContractDetailsModal({ paddingLeft={4} className="contract-details-modal__content" > - {t('contractTitle')} - - + {t('contractDescription')} - + {!isContractRequestingSignature && ( <> - {nft ? t('contractNFT') : t('contractToken')} - + )} - {tokenName || ellipsify(tokenAddress)} - + {tokenName && ( - {ellipsify(tokenAddress)} - + )} )} - + - {addressBookEntry?.data?.name || ellipsify(toAddress)} - + {addressBookEntry?.data?.name && ( - {ellipsify(toAddress)} - + )} + +
+`; diff --git a/ui/components/app/modals/customize-nonce/customize-nonce.component.js b/ui/components/app/modals/customize-nonce/customize-nonce.component.js index 58d3ab79a..4f6fba4b0 100644 --- a/ui/components/app/modals/customize-nonce/customize-nonce.component.js +++ b/ui/components/app/modals/customize-nonce/customize-nonce.component.js @@ -3,10 +3,9 @@ import PropTypes from 'prop-types'; import Modal from '../../modal'; import TextField from '../../../ui/text-field'; import Button from '../../../ui/button'; -import Typography from '../../../ui/typography'; import { - TypographyVariant, - FONT_WEIGHT, + TextVariant, + FontWeight, AlignItems, BLOCK_SIZES, DISPLAY, @@ -19,6 +18,7 @@ import { ButtonIcon, ButtonIconSize, IconName, + Text, } from '../../../component-library'; const CustomizeNonce = ({ @@ -50,13 +50,14 @@ const CustomizeNonce = ({ >
- {t('editNonceField')} - + - {t('editNonceMessage')} - + - {t('editNonceField')} - + +
+

+ Use at your own risk +

+

+ Allowing eth_sign requests can make you vulnerable to phishing attacks. Always review the URL and be careful when signing messages that contain code. + + Learn more + +

+
+ +
+ If you've been asked to turn this setting on, + you might be getting scammed +
+
+
+ + +
+
+ + +
+
+
+`; diff --git a/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js new file mode 100644 index 000000000..e6d028064 --- /dev/null +++ b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.js @@ -0,0 +1,197 @@ +import React, { useContext, useState } from 'react'; +import PropTypes from 'prop-types'; +import { useSelector, useDispatch } from 'react-redux'; +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; +import Box from '../../../ui/box'; +import { + BannerAlert, + ButtonIcon, + ButtonLink, + ButtonPrimary, + ButtonSecondary, + FormTextField, + Icon, + IconName, + IconSize, + Label, + Text, +} from '../../../component-library'; +import { + AlignItems, + DISPLAY, + FLEX_DIRECTION, + IconColor, + JustifyContent, + SEVERITIES, + Size, + TextAlign, + TextVariant, +} from '../../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import CheckBox from '../../../ui/check-box'; +import { setDisabledRpcMethodPreference } from '../../../../store/actions'; +import { getDisabledRpcMethodPreferences } from '../../../../selectors'; +import { + MetaMetricsEventCategory, + MetaMetricsEventName, +} from '../../../../../shared/constants/metametrics'; +import { MetaMetricsContext } from '../../../../contexts/metametrics'; + +const EthSignModal = ({ hideModal }) => { + const [isEthSignChecked, setIsEthSignChecked] = useState(false); + const [showTextField, setShowTextField] = useState(false); + const [inputKeyword, setInputKeyword] = useState(''); + const disabledRpcMethodPreferences = useSelector( + getDisabledRpcMethodPreferences, + ); + + const t = useI18nContext(); + const dispatch = useDispatch(); + const trackEvent = useContext(MetaMetricsContext); + + const handleSubmit = () => { + dispatch( + setDisabledRpcMethodPreference( + 'eth_sign', + !disabledRpcMethodPreferences.eth_sign, + ), + ); + hideModal(); + }; + + const isValid = inputKeyword === t('toggleEthSignModalFormValidation'); + return ( + + + + hideModal()} + ariaLabel={t('close')} + /> + + + + {t('toggleEthSignModalTitle')} + + + {t('toggleEthSignModalDescription')} + + {t('learnMoreUpperCase')} + + + + {t('toggleEthSignModalBannerText')} + {t('toggleEthSignModalBannerBoldText')} + + {showTextField ? ( + 0 && !isValid} + helpText={ + inputKeyword.length > 0 && + !isValid && + t('toggleEthSignModalFormError') + } + onChange={(event) => setInputKeyword(event.target.value)} + value={inputKeyword} + onPaste={(event) => event.preventDefault()} + /> + ) : ( + + { + setIsEthSignChecked(!isEthSignChecked); + }} + /> + + + )} + + hideModal()} size={Size.LG} block> + {t('cancel')} + + {showTextField ? ( + + {t('enableSnap')} + + ) : ( + { + setShowTextField(true); + trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.OnboardingWalletAdvancedSettings, + properties: { + location: 'Settings', + enable_eth_sign: true, + }, + }); + }} + > + {t('continue')} + + )} + + + ); +}; + +EthSignModal.propTypes = { + // The function to close the Modal + hideModal: PropTypes.func, +}; +export default withModalProps(EthSignModal); diff --git a/ui/components/app/modals/eth-sign-modal/eth-sign-modal.stories.js b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.stories.js new file mode 100644 index 000000000..bca429eab --- /dev/null +++ b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.stories.js @@ -0,0 +1,9 @@ +import React from 'react'; +import EthSignModal from './eth-sign-modal'; + +export default { + title: 'Components/App/Modals/EthSignModal', + component: EthSignModal, +}; + +export const DefaultStory = (args) => ; diff --git a/ui/components/app/modals/eth-sign-modal/eth-sign-modal.test.js b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.test.js new file mode 100644 index 000000000..98012777e --- /dev/null +++ b/ui/components/app/modals/eth-sign-modal/eth-sign-modal.test.js @@ -0,0 +1,44 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import EthSignModal from './eth-sign-modal'; + +const mockHideModal = jest.fn(); +const mockGetDisabledRpcMethodPreferences = jest.fn(); + +jest.mock('../../../../store/actions.ts', () => ({ + ...jest.requireActual('../../../../store/actions.ts'), + hideModal: () => mockHideModal, + getDisabledRpcMethodPreferences: () => mockGetDisabledRpcMethodPreferences, +})); + +describe('Eth Sign Modal', () => { + const mockState = { + appState: { + modal: { + modalState: { + props: {}, + }, + }, + }, + metamask: { + provider: { + type: 'rpc', + chainId: '0x5', + }, + disabledRpcMethodPreferences: { eth_sign: true }, + }, + }; + + const mockStore = configureMockStore([thunk])(mockState); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should match snapshot', () => { + const { container } = renderWithProvider(, mockStore); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/components/app/modals/eth-sign-modal/index.js b/ui/components/app/modals/eth-sign-modal/index.js new file mode 100644 index 000000000..cdb9572b1 --- /dev/null +++ b/ui/components/app/modals/eth-sign-modal/index.js @@ -0,0 +1 @@ +export { default } from './eth-sign-modal'; diff --git a/ui/components/app/modals/eth-sign-modal/index.scss b/ui/components/app/modals/eth-sign-modal/index.scss new file mode 100644 index 000000000..9af2b568c --- /dev/null +++ b/ui/components/app/modals/eth-sign-modal/index.scss @@ -0,0 +1,8 @@ +.eth-sign-modal { + position: relative; + + &__close { + position: absolute; + right: 16px; + } +} diff --git a/ui/components/app/modals/export-private-key-modal/__snapshots__/export-private-key-modal.test.js.snap b/ui/components/app/modals/export-private-key-modal/__snapshots__/export-private-key-modal.test.js.snap new file mode 100644 index 000000000..f275c351e --- /dev/null +++ b/ui/components/app/modals/export-private-key-modal/__snapshots__/export-private-key-modal.test.js.snap @@ -0,0 +1,120 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Export PrivateKey Modal should match snapshot 1`] = ` +
+ +
+
+`; diff --git a/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 81e0dfc4c..b50c3de85 100644 --- a/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -98,6 +98,7 @@ export default class ExportPrivateKeyModal extends Component { this.setState({ password: event.target.value })} /> ); diff --git a/ui/components/app/modals/export-private-key-modal/export-private-key-modal.test.js b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.test.js new file mode 100644 index 000000000..bc5e38df2 --- /dev/null +++ b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.test.js @@ -0,0 +1,81 @@ +import React from 'react'; +import { fireEvent } from '@testing-library/react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import mockState from '../../../../../test/data/mock-state.json'; +import * as actions from '../../../../store/actions'; +import ExportPrivateKeyModal from '.'; + +jest.mock('../../../../store/actions.ts', () => ({ + ...jest.requireActual('../../../../store/actions.ts'), + exportAccount: jest.fn().mockReturnValue(jest.fn().mockResolvedValueOnce()), + hideWarning: () => jest.fn(), + showModal: () => jest.fn(), + hideModal: () => jest.fn(), + clearAccountDetails: () => jest.fn(), +})); + +describe('Export PrivateKey Modal', () => { + const password = 'a-password'; + + const privKeyModalState = { + ...mockState, + appState: { + ...mockState.appState, + accountDetail: { + privateKey: '0xPrivKey', + }, + }, + }; + const mockStore = configureMockStore([thunk])(privKeyModalState); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + mockStore, + ); + expect(container).toMatchSnapshot(); + }); + + it('should disable confirm button by default', () => { + const { queryByText } = renderWithProvider( + , + mockStore, + ); + + const confirmButton = queryByText('Confirm'); + + expect(confirmButton).toBeDisabled(); + }); + + it('should call export account with password and selected address', () => { + const { queryByTestId, queryByText } = renderWithProvider( + , + mockStore, + ); + + const passwordInput = queryByTestId('password-input'); + + const passwordInputEvent = { + target: { + value: password, + }, + }; + + fireEvent.change(passwordInput, passwordInputEvent); + + const confirmButton = queryByText('Confirm'); + + fireEvent.click(confirmButton); + + expect(actions.exportAccount).toHaveBeenCalledWith( + password, + mockState.metamask.selectedAddress, + ); + }); +}); diff --git a/ui/components/app/modals/hide-token-confirmation-modal/__snapshots__/hide-token-confirmation-modal.test.js.snap b/ui/components/app/modals/hide-token-confirmation-modal/__snapshots__/hide-token-confirmation-modal.test.js.snap new file mode 100644 index 000000000..e12bbb688 --- /dev/null +++ b/ui/components/app/modals/hide-token-confirmation-modal/__snapshots__/hide-token-confirmation-modal.test.js.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Hide Token Confirmation Modal should match snapshot 1`] = ` +
+
+
+
+ Hide token? +
+
+
+
+ + + + + +
+
+
+
+ TKN +
+
+ You can add this token back in the future by going to “Import token” in your accounts options menu. +
+
+ + +
+
+
+
+`; diff --git a/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.test.js b/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.test.js new file mode 100644 index 000000000..6a53c80a3 --- /dev/null +++ b/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.test.js @@ -0,0 +1,84 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { fireEvent } from '@testing-library/react'; +import thunk from 'redux-thunk'; +import * as actions from '../../../../store/actions'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; +import mockState from '../../../../../test/data/mock-state.json'; +import HideTokenConfirmationModal from '.'; + +const mockHistoryPush = jest.fn(); +const mockHideModal = jest.fn(); +const mockHideToken = jest.fn().mockResolvedValue(); + +jest.mock('../../../../store/actions.ts', () => ({ + ...jest.requireActual('../../../../store/actions.ts'), + hideModal: () => mockHideModal, + hideToken: () => mockHideToken, + ignoreTokens: jest.fn().mockReturnValue(jest.fn().mockResolvedValue()), +})); + +describe('Hide Token Confirmation Modal', () => { + const tokenState = { + address: '0xTokenAddress', + symbol: 'TKN', + image: '', + }; + + const tokenModalState = { + ...mockState, + appState: { + ...mockState.appState, + modal: { + modalState: { + props: { + history: { + push: mockHistoryPush, + }, + token: tokenState, + }, + }, + }, + }, + }; + + const mockStore = configureMockStore([thunk])(tokenModalState); + + it('should match snapshot', () => { + const { container } = renderWithProvider( + , + mockStore, + ); + + expect(container).toMatchSnapshot(); + }); + + it('should hide modal', () => { + const { queryByTestId } = renderWithProvider( + , + mockStore, + ); + + const cancelButton = queryByTestId('hide-token-confirmation__cancel'); + + fireEvent.click(cancelButton); + + expect(mockHideModal).toHaveBeenCalled(); + }); + + it('should hide token with token address from state', () => { + const { queryByTestId } = renderWithProvider( + , + mockStore, + ); + + const hideButton = queryByTestId('hide-token-confirmation__hide'); + + fireEvent.click(hideButton); + + expect(mockHideModal).toHaveBeenCalled(); + expect(actions.ignoreTokens).toHaveBeenCalledWith({ + tokensToIgnore: tokenState.address, + }); + }); +}); diff --git a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js index bf4b42ccf..4a4f79581 100644 --- a/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js +++ b/ui/components/app/modals/hold-to-reveal-modal/hold-to-reveal-modal.js @@ -1,11 +1,11 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useContext } from 'react'; import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; import Box from '../../../ui/box'; import { Text, Button, - BUTTON_TYPES, + BUTTON_VARIANT, ButtonIcon, IconName, } from '../../../component-library'; @@ -20,9 +20,16 @@ import { import HoldToRevealButton from '../../hold-to-reveal-button'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url'; +import { MetaMetricsContext } from '../../../../contexts/metametrics'; +import { + MetaMetricsEventCategory, + MetaMetricsEventKeyType, + MetaMetricsEventName, +} from '../../../../../shared/constants/metametrics'; const HoldToRevealModal = ({ onLongPressed, hideModal }) => { const t = useI18nContext(); + const trackEvent = useContext(MetaMetricsContext); const unlock = () => { onLongPressed(); @@ -53,7 +60,16 @@ const HoldToRevealModal = ({ onLongPressed, hideModal }) => { className="hold-to-reveal-modal__close" iconName={IconName.Close} size={Size.SM} - onClick={handleCancel} + onClick={() => { + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpHoldToRevealCloseClicked, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + handleCancel(); + }} ariaLabel={t('close')} />
@@ -86,7 +102,7 @@ const HoldToRevealModal = ({ onLongPressed, hideModal }) => { ,
+ { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + showCustodyLabels && + ///: END:ONLY_INCLUDE_IN + } {shortenAddress(checksummedAddress)} + {showAccountCopyIcon && ( +
+ +
+ )}
{ return { selectedIdentity: getSelectedIdentity(state), + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + accountType: getAccountType(state), + accountDetails: getCustodyAccountDetails(state), + provider: getProviderConfig(state), + isCustodianSupportedChain: getIsCustodianSupportedChain(state), + ///: END:ONLY_INCLUDE_IN }; }; diff --git a/ui/components/app/signature-request-original/__snapshots__/signature-request-original.test.js.snap b/ui/components/app/signature-request-original/__snapshots__/signature-request-original.test.js.snap index 17b2c4670..368ebeec2 100644 --- a/ui/components/app/signature-request-original/__snapshots__/signature-request-original.test.js.snap +++ b/ui/components/app/signature-request-original/__snapshots__/signature-request-original.test.js.snap @@ -145,12 +145,12 @@ exports[`SignatureRequestOriginal should match snapshot 1`] = ` class="box box--display-flex box--flex-direction-column box--align-items-flex-start" >
Unknown private network
Test Account
@@ -160,12 +160,13 @@ exports[`SignatureRequestOriginal should match snapshot 1`] = ` class="box box--display-flex box--flex-direction-column box--align-items-flex-end" >
Balance
966.987986 diff --git a/ui/components/app/signature-request-original/signature-request-original.component.js b/ui/components/app/signature-request-original/signature-request-original.component.js index 9d46e92d1..cfabd20bb 100644 --- a/ui/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/components/app/signature-request-original/signature-request-original.component.js @@ -5,7 +5,13 @@ import { ObjectInspector } from 'react-inspector'; import LedgerInstructionField from '../ledger-instruction-field'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; -import { getURLHostName, sanitizeString } from '../../../helpers/utils/util'; +import { + getURLHostName, + sanitizeString, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + shortenAddress, + ///: END:ONLY_INCLUDE_IN +} from '../../../helpers/utils/util'; import { stripHexPrefix } from '../../../../shared/modules/hexstring-utils'; import Button from '../../ui/button'; import SiteOrigin from '../../ui/site-origin'; @@ -17,6 +23,13 @@ import { FONT_WEIGHT, TEXT_ALIGN, TextColor, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + IconColor, + DISPLAY, + BLOCK_SIZES, + TextVariant, + BackgroundColor, + ///: END:ONLY_INCLUDE_IN } from '../../../helpers/constants/design-system'; import { NETWORK_TYPES } from '../../../../shared/constants/network'; import { Numeric } from '../../../../shared/modules/Numeric'; @@ -26,6 +39,11 @@ import SecurityProviderBannerMessage from '../security-provider-banner-message/s import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../security-provider-banner-message/security-provider-banner-message.constants'; import { formatCurrency } from '../../../helpers/utils/confirm-tx.util'; import { getValueFromWeiHex } from '../../../../shared/modules/conversion.utils'; + +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { Icon, IconName, Text } from '../../component-library'; +import Box from '../../ui/box/box'; +///: END:ONLY_INCLUDE_IN import SignatureRequestOriginalWarning from './signature-request-original-warning'; export default class SignatureRequestOriginal extends Component { @@ -54,7 +72,10 @@ export default class SignatureRequestOriginal extends Component { messagesCount: PropTypes.number, showRejectTransactionsConfirmationModal: PropTypes.func.isRequired, cancelAll: PropTypes.func.isRequired, - provider: PropTypes.object, + providerConfig: PropTypes.object, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + selectedAccount: PropTypes.object, + ///: END:ONLY_INCLUDE_IN }; state = { @@ -62,8 +83,8 @@ export default class SignatureRequestOriginal extends Component { }; getNetworkName() { - const { provider } = this.props; - const providerName = provider.type; + const { providerConfig } = this.props; + const providerName = providerConfig.type; const { t } = this.context; switch (providerName) { @@ -78,7 +99,7 @@ export default class SignatureRequestOriginal extends Component { case NETWORK_TYPES.LOCALHOST: return t('localhost'); default: - return provider.nickname || t('unknownNetwork'); + return providerConfig.nickname || t('unknownNetwork'); } } @@ -92,6 +113,16 @@ export default class SignatureRequestOriginal extends Component { } }; + renderAccountInfo = () => { + return ( +
+ {this.renderAccount()} + {this.renderRequestIcon()} + {this.renderBalance()} +
+ ); + }; + renderTypedData = (data) => { const { t } = this.context; const { domain, message } = JSON.parse(data); @@ -152,6 +183,39 @@ export default class SignatureRequestOriginal extends Component { securityProviderResponse={txData.securityProviderResponse} /> ) : null} + + { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + this.props.selectedAccount.address === + this.props.fromAccount.address ? null : ( + + + + {this.context.t('mismatchAccount', [ + shortenAddress(this.props.selectedAccount.address), + shortenAddress(this.props.fromAccount.address), + ])} + + + ) + ///: END:ONLY_INCLUDE_IN + } +
{ @@ -130,9 +133,7 @@ describe('SignatureRequestOriginal', () => { 'Because of an error, this request was not verified by the security provider. Proceed with caution.', ), ).toBeInTheDocument(); - expect( - screen.getByText('This is based on information from'), - ).toBeInTheDocument(); + expect(screen.getByText('OpenSea')).toBeInTheDocument(); }); it('should not render SecurityProviderBannerMessage component when flagAsDangerous is not malicious', () => { @@ -147,6 +148,6 @@ describe('SignatureRequestOriginal', () => { 'Because of an error, this request was not verified by the security provider. Proceed with caution.', ), ).toBeNull(); - expect(screen.queryByText('This is based on information from')).toBeNull(); + expect(screen.queryByText('OpenSea')).toBeNull(); }); }); diff --git a/ui/components/app/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap b/ui/components/app/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap index 418b8dba0..d7106d17d 100644 --- a/ui/components/app/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap +++ b/ui/components/app/signature-request-siwe/__snapshots__/signature-request-siwe.test.js.snap @@ -122,100 +122,100 @@ exports[`SignatureRequestSIWE (Sign in with Ethereum) should match snapshot 1`] class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row" >

Message:

-
Click to sign in and accept the Terms of Service: https://community.metamask.io/tos -
+

URI:

-
http://localhost:8080 -
+

Version:

-
1 -
+

Chain ID:

-
1 -
+

Nonce:

-
STMt6KQMwwdOXE306 -
+

Issued At:

-
2023-03-18T21:40:40.823Z -
+

Resources: 2

-
ipfs://Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu https://example.com/my-web2-claim.json -
+

diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe-message/index.scss b/ui/components/app/signature-request-siwe/signature-request-siwe-message/index.scss index d78461332..36739dab5 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe-message/index.scss +++ b/ui/components/app/signature-request-siwe/signature-request-siwe-message/index.scss @@ -8,6 +8,5 @@ &__sub-text { white-space: pre-line; overflow: hidden; - word-wrap: break-word; } } diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js b/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js index e92912dda..565703ef2 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe-message/signature-request-siwe-message.js @@ -1,11 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import Box from '../../../ui/box'; -import Typography from '../../../ui/typography'; +import { Text } from '../../../component-library'; import { FLEX_DIRECTION, - TypographyVariant, + OVERFLOW_WRAP, + TextVariant, } from '../../../../helpers/constants/design-system'; const SignatureRequestSIWEMessage = ({ data }) => { @@ -14,21 +15,22 @@ const SignatureRequestSIWEMessage = ({ data }) => { {data.map(({ label, value }, i) => ( - {label} - - + {value} - + ))} diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js b/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js index 48d288bbc..fc4eef706 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe-tag/index.js @@ -1,16 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import { - TypographyVariant, + TextVariant, Size, DISPLAY, AlignItems, - FONT_WEIGHT, BackgroundColor, TextColor, } from '../../../../helpers/constants/design-system'; import Box from '../../../ui/box'; -import Typography from '../../../ui/typography/typography'; +import { Text } from '../../../component-library'; const SignatureRequestSIWETag = ({ text }) => { return ( @@ -24,14 +23,14 @@ const SignatureRequestSIWETag = ({ text }) => { paddingLeft={4} paddingRight={4} > - {text} - + ); }; diff --git a/ui/components/app/signature-request-siwe/signature-request-siwe.js b/ui/components/app/signature-request-siwe/signature-request-siwe.js index de7441cb7..82f46e746 100644 --- a/ui/components/app/signature-request-siwe/signature-request-siwe.js +++ b/ui/components/app/signature-request-siwe/signature-request-siwe.js @@ -2,6 +2,7 @@ import React, { useCallback, useContext, useState } from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import log from 'loglevel'; +import { isValidSIWEOrigin } from '@metamask/controller-utils'; import { BannerAlert, Text } from '../../component-library'; import Popover from '../../ui/popover'; import Checkbox from '../../ui/check-box'; @@ -51,20 +52,18 @@ export default function SignatureRequestSIWE({ const isMatchingAddress = from.toLowerCase() === parsedMessage.address.toLowerCase(); - const checkSIWEDomain = () => { - let isSIWEDomainValid = false; - - if (origin) { - const { host } = new URL(origin); - isSIWEDomainValid = parsedMessage.domain === host; - } - return isSIWEDomainValid; - }; - - const isSIWEDomainValid = checkSIWEDomain(); + const isSIWEDomainValid = isValidSIWEOrigin(txData.msgParams); const [isShowingDomainWarning, setIsShowingDomainWarning] = useState(false); - const [agreeToDomainWarning, setAgreeToDomainWarning] = useState(false); + const [hasAgreedToDomainWarning, setHasAgreedToDomainWarning] = + useState(false); + + const showSecurityProviderBanner = + (txData?.securityProviderResponse?.flagAsDangerous !== undefined && + txData?.securityProviderResponse?.flagAsDangerous !== + SECURITY_PROVIDER_MESSAGE_SEVERITIES.NOT_MALICIOUS) || + (txData?.securityProviderResponse && + Object.keys(txData.securityProviderResponse).length === 0); const onSign = useCallback( async (event) => { @@ -96,15 +95,13 @@ export default function SignatureRequestSIWE({ isSIWEDomainValid={isSIWEDomainValid} subjectMetadata={targetSubjectMetadata} /> - {(txData?.securityProviderResponse?.flagAsDangerous !== undefined && - txData?.securityProviderResponse?.flagAsDangerous !== - SECURITY_PROVIDER_MESSAGE_SEVERITIES.NOT_MALICIOUS) || - (txData?.securityProviderResponse && - Object.keys(txData.securityProviderResponse).length === 0) ? ( + + {showSecurityProviderBanner && ( - ) : null} + )} + {!isMatchingAddress && ( } >
setAgreeToDomainWarning((checked) => !checked)} + onClick={() => setHasAgreedToDomainWarning((checked) => !checked)} />
@@ -44,7 +44,7 @@ exports[`TransactionStatusLabel Component should render QUEUED properly 1`] = `
- [queued] + Queued
`; @@ -54,7 +54,7 @@ exports[`TransactionStatusLabel Component should render UNAPPROVED properly 1`]
- [unapproved] + Unapproved
`; diff --git a/ui/components/app/transaction-status-label/transaction-status-label.js b/ui/components/app/transaction-status-label/transaction-status-label.js index c0ea92b4b..6c9f79921 100644 --- a/ui/components/app/transaction-status-label/transaction-status-label.js +++ b/ui/components/app/transaction-status-label/transaction-status-label.js @@ -1,6 +1,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { useSelector } from 'react-redux'; +///: END:ONLY_INCLUDE_IN import Tooltip from '../../ui/tooltip'; import { useI18nContext } from '../../../hooks/useI18nContext'; @@ -9,7 +12,15 @@ import { TransactionStatus, } from '../../../../shared/constants/transaction'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { getTransactionStatusMap } from '../../../selectors/institutional/selectors'; +import { getCurrentKeyring } from '../../../selectors'; +///: END:ONLY_INCLUDE_IN + const QUEUED_PSEUDO_STATUS = 'queued'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +const CUSTODIAN_PSEUDO_STATUS = 'inCustody'; +///: END:ONLY_INCLUDE_IN /** * A note about status logic for this component: @@ -35,6 +46,9 @@ const statusToClassNameHash = { [TransactionGroupStatus.cancelled]: 'transaction-status-label--cancelled', [QUEUED_PSEUDO_STATUS]: 'transaction-status-label--queued', [TransactionGroupStatus.pending]: 'transaction-status-label--pending', + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + [CUSTODIAN_PSEUDO_STATUS]: 'transaction-status--custodian', + ///: END:ONLY_INCLUDE_IN }; export default function TransactionStatusLabel({ @@ -44,9 +58,13 @@ export default function TransactionStatusLabel({ isEarliestNonce, className, statusOnly, + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + custodyStatus, + custodyStatusDisplayText, + ///: END:ONLY_INCLUDE_IN }) { const t = useI18nContext(); - const tooltipText = error?.rpc?.message || error?.message; + let tooltipText = error?.rpc?.message || error?.message; let statusKey = status; if (pendingStatusHash[status]) { statusKey = isEarliestNonce @@ -54,10 +72,43 @@ export default function TransactionStatusLabel({ : QUEUED_PSEUDO_STATUS; } - const statusText = - statusKey === TransactionStatus.confirmed && !statusOnly - ? date - : statusKey && t(statusKey); + let statusText = statusKey && t(statusKey); + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + statusText = custodyStatusDisplayText || t(statusKey); + ///: END:ONLY_INCLUDE_IN + + if (statusKey === TransactionStatus.confirmed && !statusOnly) { + statusText = date; + } + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const transactionStatusMap = useSelector(getTransactionStatusMap); + const currentKeyring = useSelector(getCurrentKeyring); + const custodyType = currentKeyring?.type.split(' - ')[1]?.toLowerCase(); + + if ( + custodyStatus && + transactionStatusMap && + transactionStatusMap[custodyType] + ) { + const custodyStatusInfo = transactionStatusMap[custodyType][custodyStatus]; + const shortText = custodyStatusInfo?.shortText || custodyStatus; + const longText = custodyStatusInfo?.longText; + + if (error) { + tooltipText = error.message; + statusText = + custodyStatus === 'aborted' + ? custodyStatusDisplayText + : t('snapResultError'); + } else { + tooltipText = custodyStatusDisplayText || longText || custodyStatus; + statusText = custodyStatusDisplayText || shortText; + } + } + + ///: END:ONLY_INCLUDE_IN return ( { + const createMockStore = configureMockStore([thunk]); + const mockState = { + metamask: { + custodyStatusMaps: {}, + identities: {}, + selectedAddress: 'fakeAddress', + }, + }; + + let store = createMockStore(mockState); it('should render CONFIRMED properly', () => { const confirmedProps = { status: 'confirmed', @@ -11,6 +23,7 @@ describe('TransactionStatusLabel Component', () => { const { container } = renderWithProvider( , + store, ); expect(container).toMatchSnapshot(); @@ -25,6 +38,7 @@ describe('TransactionStatusLabel Component', () => { const { container } = renderWithProvider( , + store, ); expect(container).toMatchSnapshot(); @@ -39,6 +53,7 @@ describe('TransactionStatusLabel Component', () => { const { container } = renderWithProvider( , + store, ); expect(container).toMatchSnapshot(); @@ -51,6 +66,7 @@ describe('TransactionStatusLabel Component', () => { const { container } = renderWithProvider( , + store, ); expect(container).toMatchSnapshot(); @@ -63,8 +79,153 @@ describe('TransactionStatusLabel Component', () => { const { container } = renderWithProvider( , + store, ); expect(container).toMatchSnapshot(); }); + + it('should render statusText properly when is custodyStatusDisplayText is defined', () => { + const props = { + custodyStatusDisplayText: 'test', + }; + + const { getByText } = renderWithProvider( + , + store, + ); + + expect(getByText(props.custodyStatusDisplayText)).toBeVisible(); + }); + + it('should display the correct status text and tooltip', () => { + const mockShortText = 'Short Text Test'; + const mockLongText = 'Long Text Test'; + const props = { + status: 'approved', + custodyStatus: 'approved', + }; + const customMockStore = { + metamask: { + custodyStatusMaps: { + jupiter: { + approved: { + shortText: mockShortText, + longText: mockLongText, + }, + }, + }, + selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + identities: { + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + name: 'Account 1', + }, + }, + keyrings: [ + { + type: 'Custody - Jupiter', + accounts: ['0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'], + }, + ], + }, + }; + + store = createMockStore(customMockStore); + + const { getByText } = renderWithProvider( + , + store, + ); + + expect(getByText(mockShortText)).toBeVisible(); + }); + it('should display the error message when there is an error', () => { + const mockShortText = 'Short Text Test'; + const mockLongText = 'Long Text Test'; + const props = { + status: 'approved', + custodyStatus: 'approved', + error: { message: 'An error occurred' }, + }; + const customMockStore = { + metamask: { + custodyStatusMaps: { + jupiter: { + approved: { + shortText: mockShortText, + longText: mockLongText, + }, + }, + }, + selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + identities: { + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + name: 'Account 1', + }, + }, + keyrings: [ + { + type: 'Custody - Jupiter', + accounts: ['0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'], + }, + ], + }, + }; + + store = createMockStore(customMockStore); + + const { getByText } = renderWithProvider( + , + store, + ); + + expect(getByText('Error')).toBeVisible(); + }); + + it('should display correctly the error message when there is an error and custodyStatus is aborted', () => { + const mockShortText = 'Short Text Test'; + const mockLongText = 'Long Text Test'; + const props = { + status: 'approved', + custodyStatus: 'aborted', + error: { message: 'An error occurred' }, + custodyStatusDisplayText: 'Test', + }; + const customMockStore = { + metamask: { + custodyStatusMaps: { + jupiter: { + approved: { + shortText: mockShortText, + longText: mockLongText, + }, + }, + }, + selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + identities: { + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + name: 'Account 1', + }, + }, + keyrings: [ + { + type: 'Custody - Jupiter', + accounts: ['0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'], + }, + ], + }, + }; + + store = createMockStore(customMockStore); + + const { getByText } = renderWithProvider( + , + store, + ); + + expect(getByText(props.custodyStatusDisplayText)).toBeVisible(); + }); }); diff --git a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js index 046964bb3..93ed738ee 100644 --- a/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.test.js @@ -7,7 +7,7 @@ describe('UserPreferencedCurrencyDisplay Component', () => { describe('rendering', () => { const mockState = { metamask: { - provider: { + providerConfig: { chainId: '0x99', }, preferences: { diff --git a/ui/components/app/wallet-overview/eth-overview.js b/ui/components/app/wallet-overview/eth-overview.js index 04cace94f..09d3a936f 100644 --- a/ui/components/app/wallet-overview/eth-overview.js +++ b/ui/components/app/wallet-overview/eth-overview.js @@ -4,6 +4,13 @@ import { useDispatch, useSelector } from 'react-redux'; import classnames from 'classnames'; import { useHistory, useLocation } from 'react-router-dom'; +///: BEGIN:ONLY_INCLUDE_IN(build-mmi) +import { + getMmiPortfolioEnabled, + getMmiPortfolioUrl, +} from '../../../selectors/institutional/selectors'; +///: END:ONLY_INCLUDE_IN + import Identicon from '../../ui/identicon'; import { I18nContext } from '../../../contexts/i18n'; import { @@ -23,6 +30,8 @@ import { getIsBuyableChain, getNativeCurrencyImage, getSelectedAccountCachedBalance, + getCurrentChainId, + getMetaMetricsId, } from '../../../selectors'; import { setSwapsFromToken } from '../../../ducks/swaps/swaps'; import IconButton from '../../ui/icon-button'; @@ -45,6 +54,7 @@ import { } from '../../component-library'; import { IconColor } from '../../../helpers/constants/design-system'; import useRamps from '../../../hooks/experiences/useRamps'; +import { getPortfolioUrl } from '../../../helpers/utils/portfolio'; import WalletOverview from './wallet-overview'; const EthOverview = ({ className }) => { @@ -63,6 +73,58 @@ const EthOverview = ({ className }) => { const isBuyableChain = useSelector(getIsBuyableChain); const primaryTokenImage = useSelector(getNativeCurrencyImage); const defaultSwapsToken = useSelector(getSwapsDefaultToken); + const chainId = useSelector(getCurrentChainId); + const metaMetricsId = useSelector(getMetaMetricsId); + + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + const mmiPortfolioEnabled = useSelector(getMmiPortfolioEnabled); + const mmiPortfolioUrl = useSelector(getMmiPortfolioUrl); + + const portfolioEvent = () => { + trackEvent({ + category: 'Navigation', + event: 'Clicked Portfolio Button', + }); + }; + + const stakingEvent = () => { + trackEvent({ + category: 'Navigation', + event: 'Clicked Stake Button', + }); + }; + + const renderInstitutionalButtons = () => { + return ( + <> + } + label={t('stake')} + onClick={() => { + stakingEvent(); + global.platform.openTab({ + url: 'https://metamask-institutional.io/staking', + }); + }} + /> + {mmiPortfolioEnabled && ( + + } + label={t('portfolio')} + onClick={() => { + portfolioEvent(); + window.open(mmiPortfolioUrl, '_blank'); + }} + /> + )} + + ); + }; + ///: END:ONLY_INCLUDE_IN const { openBuyCryptoInPdapp } = useRamps(); @@ -98,36 +160,44 @@ const EthOverview = ({ className }) => { {balanceIsCached ? ( * ) : null} - {process.env.MULTICHAIN ? null : ( - { - const portfolioUrl = process.env.PORTFOLIO_URL; - global.platform.openTab({ - url: `${portfolioUrl}?metamaskEntry=ext`, - }); - trackEvent( - { - category: MetaMetricsEventCategory.Home, - event: MetaMetricsEventName.PortfolioLinkClicked, - properties: { - url: portfolioUrl, + { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) + process.env.MULTICHAIN ? null : ( + { + const portfolioUrl = getPortfolioUrl( + '', + 'ext', + metaMetricsId, + ); + global.platform.openTab({ + url: portfolioUrl, + }); + trackEvent( + { + category: MetaMetricsEventCategory.Home, + event: MetaMetricsEventName.PortfolioLinkClicked, + properties: { + url: portfolioUrl, + }, }, - }, - { - contextPropsIntoEventProperties: [ - MetaMetricsContextProp.PageTitle, - ], - }, - ); - }} - /> - )} + { + contextPropsIntoEventProperties: [ + MetaMetricsContextProp.PageTitle, + ], + }, + ); + }} + /> + ) + ///: END:ONLY_INCLUDE_IN + }
{showFiat && balance && ( { } buttons={ <> - } - disabled={!isBuyableChain} - data-testid="eth-overview-buy" - label={t('buy')} - onClick={() => { - openBuyCryptoInPdapp(); - trackEvent({ - event: MetaMetricsEventName.NavBuyButtonClicked, - category: MetaMetricsEventCategory.Navigation, - properties: { - location: 'Home', - text: 'Buy', - }, - }); - }} - /> + { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) + + } + disabled={!isBuyableChain} + data-testid="eth-overview-buy" + label={t('buy')} + onClick={() => { + openBuyCryptoInPdapp(); + trackEvent({ + event: MetaMetricsEventName.NavBuyButtonClicked, + category: MetaMetricsEventCategory.Navigation, + properties: { + location: 'Home', + text: 'Buy', + chain_id: chainId, + token_symbol: defaultSwapsToken, + }, + }); + }} + /> + ///: END:ONLY_INCLUDE_IN + } + + { + ///: BEGIN:ONLY_INCLUDE_IN(build-mmi) + renderInstitutionalButtons() + ///: END:ONLY_INCLUDE_IN + } + { token_symbol: 'ETH', location: 'Home', text: 'Send', + chain_id: chainId, }, }); dispatch( @@ -210,6 +296,7 @@ const EthOverview = ({ className }) => { token_symbol: 'ETH', location: MetaMetricsSwapsEventSource.MainView, text: 'Swap', + chain_id: chainId, }, }); dispatch(setSwapsFromToken(defaultSwapsToken)); @@ -234,46 +321,55 @@ const EthOverview = ({ className }) => { ) } /> - - } - label={t('bridge')} - onClick={() => { - if (isBridgeChain) { - const portfolioUrl = process.env.PORTFOLIO_URL; - const bridgeUrl = `${portfolioUrl}/bridge`; - global.platform.openTab({ - url: `${bridgeUrl}?metamaskEntry=ext_bridge_button${ - location.pathname.includes('asset') ? '&token=native' : '' - }`, - }); - trackEvent({ - category: MetaMetricsEventCategory.Navigation, - event: MetaMetricsEventName.BridgeLinkClicked, - properties: { - location: 'Home', - text: 'Bridge', - }, - }); + { + ///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask) + } - }} - tooltipRender={ - isBridgeChain - ? null - : (contents) => ( - - {contents} - - ) - } - /> + label={t('bridge')} + onClick={() => { + if (isBridgeChain) { + const portfolioUrl = getPortfolioUrl( + 'bridge', + 'ext_bridge_button', + metaMetricsId, + ); + global.platform.openTab({ + url: `${portfolioUrl}${ + location.pathname.includes('asset') ? '&token=native' : '' + }`, + }); + trackEvent({ + category: MetaMetricsEventCategory.Navigation, + event: MetaMetricsEventName.BridgeLinkClicked, + properties: { + location: 'Home', + text: 'Bridge', + chain_id: chainId, + token_symbol: 'ETH', + }, + }); + } + }} + tooltipRender={ + isBridgeChain + ? null + : (contents) => ( + + {contents} + + ) + } + /> + ///: END:ONLY_INCLUDE_IN + } } className={className} diff --git a/ui/components/app/wallet-overview/eth-overview.test.js b/ui/components/app/wallet-overview/eth-overview.test.js index a237e6879..79a183700 100644 --- a/ui/components/app/wallet-overview/eth-overview.test.js +++ b/ui/components/app/wallet-overview/eth-overview.test.js @@ -28,7 +28,7 @@ let openTabSpy; describe('EthOverview', () => { const mockStore = { metamask: { - provider: { + providerConfig: { type: 'test', chainId: CHAIN_IDS.MAINNET, }, @@ -150,7 +150,10 @@ describe('EthOverview', () => { ...mockStore, metamask: { ...mockStore.metamask, - provider: { ...mockStore.metamask.provider, chainId: '0xa86a' }, + providerConfig: { + ...mockStore.metamask.providerConfig, + chainId: '0xa86a', + }, }, }; const mockedStore = configureMockStore([thunk])(mockedAvalancheStore); @@ -193,7 +196,10 @@ describe('EthOverview', () => { ...mockStore, metamask: { ...mockStore.metamask, - provider: { ...mockStore.metamask.provider, chainId: '0xfa' }, + providerConfig: { + ...mockStore.metamask.providerConfig, + chainId: '0xfa', + }, }, }; const mockedStore = configureMockStore([thunk])(mockedFantomStore); @@ -245,7 +251,7 @@ describe('EthOverview', () => { const mockedStoreWithUnbuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.FANTOM }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.FANTOM }, }, }; const mockedStore = configureMockStore([thunk])( @@ -265,7 +271,7 @@ describe('EthOverview', () => { const mockedStoreWithUnbuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( @@ -285,7 +291,7 @@ describe('EthOverview', () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( diff --git a/ui/components/app/wallet-overview/token-overview.js b/ui/components/app/wallet-overview/token-overview.js index ed99cabee..fff89e457 100644 --- a/ui/components/app/wallet-overview/token-overview.js +++ b/ui/components/app/wallet-overview/token-overview.js @@ -20,6 +20,8 @@ import { getIsSwapsChain, getIsBuyableChain, getIsBridgeToken, + getCurrentChainId, + getMetaMetricsId, } from '../../../selectors'; import IconButton from '../../ui/icon-button'; @@ -39,6 +41,7 @@ import { ButtonIcon, Icon, IconName } from '../../component-library'; import { IconColor } from '../../../helpers/constants/design-system'; import { BUTTON_ICON_SIZES } from '../../component-library/button-icon/deprecated'; +import { getPortfolioUrl } from '../../../helpers/utils/portfolio'; import WalletOverview from './wallet-overview'; const TokenOverview = ({ className, token }) => { @@ -56,9 +59,11 @@ const TokenOverview = ({ className, token }) => { balanceToRender, token.symbol, ); + const chainId = useSelector(getCurrentChainId); const isSwapsChain = useSelector(getIsSwapsChain); const isBridgeToken = useSelector(getIsBridgeToken(token.address)); const isBuyableChain = useSelector(getIsBuyableChain); + const metaMetricsId = useSelector(getMetaMetricsId); const { openBuyCryptoInPdapp } = useRamps(); @@ -92,9 +97,9 @@ const TokenOverview = ({ className, token }) => { ariaLabel={t('portfolio')} size={BUTTON_ICON_SIZES.LG} onClick={() => { - const portfolioUrl = process.env.PORTFOLIO_URL; + const portfolioUrl = getPortfolioUrl('', 'ext', metaMetricsId); global.platform.openTab({ - url: `${portfolioUrl}?metamaskEntry=ext`, + url: portfolioUrl, }); trackEvent( { @@ -137,6 +142,8 @@ const TokenOverview = ({ className, token }) => { properties: { location: 'Token Overview', text: 'Buy', + chain_id: chainId, + token_symbol: token.symbol, }, }); }} @@ -152,6 +159,7 @@ const TokenOverview = ({ className, token }) => { token_symbol: token.symbol, location: MetaMetricsSwapsEventSource.TokenView, text: 'Send', + chain_id: chainId, }, }); try { @@ -195,6 +203,7 @@ const TokenOverview = ({ className, token }) => { token_symbol: token.symbol, location: MetaMetricsSwapsEventSource.TokenView, text: 'Swap', + chain_id: chainId, }, }); dispatch( @@ -225,11 +234,13 @@ const TokenOverview = ({ className, token }) => { } label={t('bridge')} onClick={() => { - const portfolioUrl = process.env.PORTFOLIO_URL; - - const bridgeUrl = `${portfolioUrl}/bridge`; + const portfolioUrl = getPortfolioUrl( + 'bridge', + 'ext_bridge_button', + metaMetricsId, + ); global.platform.openTab({ - url: `${bridgeUrl}?metamaskEntry=ext_bridge_button&token=${token.address}`, + url: `${portfolioUrl}&token=${token.address}`, }); trackEvent({ category: MetaMetricsEventCategory.Navigation, @@ -237,6 +248,9 @@ const TokenOverview = ({ className, token }) => { properties: { location: 'Token Overview', text: 'Bridge', + url: portfolioUrl, + chain_id: chainId, + token_symbol: token.symbol, }, }); }} diff --git a/ui/components/app/wallet-overview/token-overview.test.js b/ui/components/app/wallet-overview/token-overview.test.js index 707b02921..8a5495858 100644 --- a/ui/components/app/wallet-overview/token-overview.test.js +++ b/ui/components/app/wallet-overview/token-overview.test.js @@ -28,7 +28,7 @@ let openTabSpy; describe('TokenOverview', () => { const mockStore = { metamask: { - provider: { + providerConfig: { type: 'test', chainId: CHAIN_IDS.MAINNET, }, @@ -110,7 +110,7 @@ describe('TokenOverview', () => { const mockedStoreWithUnbuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.PALM }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.PALM }, }, }; const mockedStore = configureMockStore([thunk])( @@ -143,7 +143,7 @@ describe('TokenOverview', () => { const mockedStoreWithUnbuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.FANTOM }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.FANTOM }, }, }; const mockedStore = configureMockStore([thunk])( @@ -163,7 +163,7 @@ describe('TokenOverview', () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( @@ -188,7 +188,7 @@ describe('TokenOverview', () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( @@ -208,7 +208,7 @@ describe('TokenOverview', () => { const mockedStoreWithBuyableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( @@ -286,7 +286,7 @@ describe('TokenOverview', () => { const mockedStoreWithBridgeableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( @@ -307,7 +307,7 @@ describe('TokenOverview', () => { await waitFor(() => expect(openTabSpy).toHaveBeenCalledWith({ url: expect.stringContaining( - '/bridge?metamaskEntry=ext_bridge_button&token=0x7ceb23fd6bc0add59e62ac25578270cff1B9f619', + '/bridge?metamaskEntry=ext_bridge_button&metametricsId=&token=0x7ceb23fd6bc0add59e62ac25578270cff1B9f619', ), }), ); @@ -324,7 +324,7 @@ describe('TokenOverview', () => { const mockedStoreWithBridgeableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.FANTOM }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.FANTOM }, }, }; const mockedStore = configureMockStore([thunk])( @@ -350,7 +350,7 @@ describe('TokenOverview', () => { const mockedStoreWithBridgeableChainId = { metamask: { ...mockStore.metamask, - provider: { type: 'test', chainId: CHAIN_IDS.POLYGON }, + providerConfig: { type: 'test', chainId: CHAIN_IDS.POLYGON }, }, }; const mockedStore = configureMockStore([thunk])( diff --git a/ui/components/app/wallet-overview/wallet-overview.js b/ui/components/app/wallet-overview/wallet-overview.js index 5be0ef73b..7cc9642aa 100644 --- a/ui/components/app/wallet-overview/wallet-overview.js +++ b/ui/components/app/wallet-overview/wallet-overview.js @@ -5,6 +5,7 @@ import { useSelector } from 'react-redux'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { getSelectedIdentity } from '../../../selectors'; import { AddressCopyButton } from '../../multichain'; +import Box from '../../ui/box/box'; const WalletOverview = ({ balance, buttons, className, icon, loading }) => { const selectedIdentity = useSelector(getSelectedIdentity); @@ -13,7 +14,9 @@ const WalletOverview = ({ balance, buttons, className, icon, loading }) => {
{process.env.MULTICHAIN ? ( - + + + ) : ( <>{loading ? null : icon} )} diff --git a/ui/components/app/whats-new-popup/whats-new-popup.js b/ui/components/app/whats-new-popup/whats-new-popup.js index fd0bf14a7..12f81a60c 100644 --- a/ui/components/app/whats-new-popup/whats-new-popup.js +++ b/ui/components/app/whats-new-popup/whats-new-popup.js @@ -20,6 +20,11 @@ import { } from '../../../helpers/constants/routes'; import { TextVariant } from '../../../helpers/constants/design-system'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + MetaMetricsEventCategory, + MetaMetricsEventName, +} from '../../../../shared/constants/metametrics'; function getActionFunctionById(id, history) { const actionFunctions = { @@ -107,9 +112,16 @@ const renderDescription = (description) => { ); }; -const renderFirstNotification = (notification, idRefMap, history, isLast) => { +const renderFirstNotification = ( + notification, + idRefMap, + history, + isLast, + trackEvent, +) => { const { id, date, title, description, image, actionText } = notification; const actionFunction = getActionFunctionById(id, history); + const imageComponent = image && ( { @@ -218,6 +236,8 @@ export default function WhatsNewPopup({ onClose }) { [memoizedNotifications], ); + const trackEvent = useContext(MetaMetricsContext); + const handleScrollDownClick = (e) => { e.stopPropagation(); idRefMap[notifications[notifications.length - 1].id].current.scrollIntoView( @@ -267,6 +287,14 @@ export default function WhatsNewPopup({ onClose }) { className="whats-new-popup__popover" onClose={() => { updateViewedNotifications(seenNotifications); + trackEvent({ + category: MetaMetricsEventCategory.Home, + event: MetaMetricsEventName.WhatsNewViewed, + properties: { + number_viewed: Object.keys(seenNotifications).pop(), + completed_all: true, + }, + }); onClose(); }} popoverRef={popoverRef} @@ -280,7 +308,13 @@ export default function WhatsNewPopup({ onClose }) { // Display the swaps notification with full image // Displays the NFTs & OpenSea notifications 18,19 with full image return index === 0 || id === 1 || id === 18 || id === 19 - ? renderFirstNotification(notification, idRefMap, history, isLast) + ? renderFirstNotification( + notification, + idRefMap, + history, + isLast, + trackEvent, + ) : renderSubsequentNotification( notification, idRefMap, diff --git a/ui/components/component-library/README.md b/ui/components/component-library/README.md index 8c3c27f74..3565bf664 100644 --- a/ui/components/component-library/README.md +++ b/ui/components/component-library/README.md @@ -10,22 +10,22 @@ All components are built on top of the `Box` component and accept all `Box` [com `component-library` components accept all utility props for layout -``` -import { Text } from '../../component-library' +```jsx +import { Text } from '../../component-library'; -This text has a margin-bottom of 16px +This text has a margin-bottom of 16px; ``` #### Polymorphic `as` prop `component-library` components accept a polymorphic as prop to change the root html element of a component -``` -import { Text } from '../../component-library' +```jsx +import { Text } from '../../component-library';
    -This renders as list item html element -
+ This renders as list item html element +; ``` ## TypeScript diff --git a/ui/components/component-library/avatar-account/avatar-account.js b/ui/components/component-library/avatar-account/avatar-account.js index fd1fee73a..286024253 100644 --- a/ui/components/component-library/avatar-account/avatar-account.js +++ b/ui/components/component-library/avatar-account/avatar-account.js @@ -13,32 +13,38 @@ import { AvatarAccountSize, } from './avatar-account.types'; -export const AvatarAccount = ({ - size = AvatarAccountSize.Md, - address, - className, - variant = AvatarAccountVariant.Jazzicon, - ...props -}) => ( - - {variant === AvatarAccountVariant.Jazzicon ? ( - - ) : ( - - )} - +export const AvatarAccount = React.forwardRef( + ( + { + size = AvatarAccountSize.Md, + address, + className, + variant = AvatarAccountVariant.Jazzicon, + ...props + }, + ref, + ) => ( + + {variant === AvatarAccountVariant.Jazzicon ? ( + + ) : ( + + )} + + ), ); AvatarAccount.propTypes = { @@ -66,3 +72,5 @@ AvatarAccount.propTypes = { */ ...Box.propTypes, }; + +AvatarAccount.displayName = 'AvatarAccount'; diff --git a/ui/components/component-library/avatar-account/avatar-account.test.js b/ui/components/component-library/avatar-account/avatar-account.test.js index 1350daa01..7d7837bdc 100644 --- a/ui/components/component-library/avatar-account/avatar-account.test.js +++ b/ui/components/component-library/avatar-account/avatar-account.test.js @@ -112,4 +112,15 @@ describe('AvatarAccount', () => { 'mm-avatar-base--size-xl', ); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render( + , + ); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/avatar-base/README.mdx b/ui/components/component-library/avatar-base/README.mdx index d232dfc10..da27d6677 100644 --- a/ui/components/component-library/avatar-base/README.mdx +++ b/ui/components/component-library/avatar-base/README.mdx @@ -39,13 +39,13 @@ The text styles of the `AvatarBase` is based on the `size` prop. To override thi ```jsx -import { AVATAR_BASE_SIZES } from '../ui/component-library/avatar-base'; -import { AvatarBase } from '../../component-library'; - - - - - +import { AvatarBaseSize } from '../ui/component-library/avatar-base/avatar-base.types'; +import { AvatarBase } from '../../component-library/avatar-base'; + + + + + ``` ### Children diff --git a/ui/components/component-library/avatar-base/__snapshots__/avatar-base.test.js.snap b/ui/components/component-library/avatar-base/__snapshots__/avatar-base.test.tsx.snap similarity index 100% rename from ui/components/component-library/avatar-base/__snapshots__/avatar-base.test.js.snap rename to ui/components/component-library/avatar-base/__snapshots__/avatar-base.test.tsx.snap diff --git a/ui/components/component-library/avatar-base/avatar-base.constants.js b/ui/components/component-library/avatar-base/avatar-base.constants.js deleted file mode 100644 index 6adba7a62..000000000 --- a/ui/components/component-library/avatar-base/avatar-base.constants.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Size } from '../../../helpers/constants/design-system'; - -export const AVATAR_BASE_SIZES = { - XS: Size.XS, - SM: Size.SM, - MD: Size.MD, - LG: Size.LG, - XL: Size.XL, -}; diff --git a/ui/components/component-library/avatar-base/avatar-base.js b/ui/components/component-library/avatar-base/avatar-base.js deleted file mode 100644 index 7b981e04a..000000000 --- a/ui/components/component-library/avatar-base/avatar-base.js +++ /dev/null @@ -1,97 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; - -import { - BackgroundColor, - BorderColor, - TextColor, - IconColor, - DISPLAY, - JustifyContent, - AlignItems, - BorderRadius, - TextVariant, - TEXT_TRANSFORM, -} from '../../../helpers/constants/design-system'; - -import { Text } from '../text'; - -import { AVATAR_BASE_SIZES } from './avatar-base.constants'; - -export const AvatarBase = ({ - size = AVATAR_BASE_SIZES.MD, - children, - backgroundColor = BackgroundColor.backgroundAlternative, - borderColor = BorderColor.borderDefault, - color = TextColor.textDefault, - className, - ...props -}) => { - let fallbackTextVariant; - - if (size === AVATAR_BASE_SIZES.LG || size === AVATAR_BASE_SIZES.XL) { - fallbackTextVariant = TextVariant.bodyLgMedium; - } else if (size === AVATAR_BASE_SIZES.SM || size === AVATAR_BASE_SIZES.MD) { - fallbackTextVariant = TextVariant.bodySm; - } else { - fallbackTextVariant = TextVariant.bodyXs; - } - return ( - - {children} - - ); -}; -AvatarBase.propTypes = { - /** - * The size of the AvatarBase. - * Possible values could be 'AVATAR_BASE_SIZES.XS'(16px), 'AVATAR_BASE_SIZES.SM'(24px), 'AVATAR_BASE_SIZES.MD'(32px), 'AVATAR_BASE_SIZES.LG'(40px), 'AVATAR_BASE_SIZES.XL'(48px) - * Defaults to AVATAR_BASE_SIZES.MD - */ - size: PropTypes.oneOf(Object.values(AVATAR_BASE_SIZES)), - /** - * The children to be rendered inside the AvatarBase - */ - children: PropTypes.node, - /** - * The background color of the AvatarBase - * Defaults to Color.backgroundAlternative - */ - backgroundColor: PropTypes.oneOf(Object.values(BackgroundColor)), - /** - * The background color of the AvatarBase - * Defaults to Color.borderDefault - */ - borderColor: PropTypes.oneOf(Object.values(BorderColor)), - /** - * The color of the text inside the AvatarBase - * Defaults to TextColor.textDefault - */ - color: PropTypes.oneOf([ - ...Object.values(TextColor), - ...Object.values(IconColor), - ]), - /** - * Additional classNames to be added to the AvatarToken - */ - className: PropTypes.string, - /** - * AvatarBase also accepts all Text props including variant and all Box props - */ - ...Text.propTypes, -}; diff --git a/ui/components/component-library/avatar-base/avatar-base.stories.js b/ui/components/component-library/avatar-base/avatar-base.stories.tsx similarity index 77% rename from ui/components/component-library/avatar-base/avatar-base.stories.js rename to ui/components/component-library/avatar-base/avatar-base.stories.tsx index cd86e81d1..85852edde 100644 --- a/ui/components/component-library/avatar-base/avatar-base.stories.js +++ b/ui/components/component-library/avatar-base/avatar-base.stories.tsx @@ -1,3 +1,4 @@ +import { ComponentMeta } from '@storybook/react'; import React from 'react'; import { AlignItems, @@ -5,7 +6,7 @@ import { TextColor, BackgroundColor, BorderColor, - Color, + IconColor, } from '../../../helpers/constants/design-system'; import Box from '../../ui/box/box'; @@ -13,7 +14,7 @@ import Box from '../../ui/box/box'; import { Icon, IconName } from '..'; import README from './README.mdx'; import { AvatarBase } from './avatar-base'; -import { AVATAR_BASE_SIZES } from './avatar-base.constants'; +import { AvatarBaseProps, AvatarBaseSize } from './avatar-base.types'; const marginSizeKnobOptions = [ 0, @@ -44,7 +45,7 @@ export default { argTypes: { size: { control: 'select', - options: Object.values(AVATAR_BASE_SIZES), + options: Object.values(AvatarBaseSize), }, color: { options: Object.values(TextColor), @@ -85,29 +86,29 @@ export default { }, }, args: { - size: AVATAR_BASE_SIZES.MD, + size: AvatarBaseSize.Md, color: TextColor.textDefault, backgroundColor: BackgroundColor.backgroundAlternative, borderColor: BorderColor.borderDefault, children: 'B', }, -}; +} as ComponentMeta; -export const DefaultStory = (args) => ; +export const DefaultStory = (args: AvatarBaseProps) => ; DefaultStory.storyName = 'Default'; -export const Size = (args) => ( +export const Size = (args: AvatarBaseProps) => ( - - - - - + + + + + ); -export const Children = (args) => ( +export const Children = (args: AvatarBaseProps) => ( @@ -124,12 +125,12 @@ export const Children = (args) => ( backgroundColor={BackgroundColor.infoMuted} borderColor={BorderColor.infoMuted} > - + ); -export const ColorBackgroundColorAndBorderColor = (args) => ( +export const ColorBackgroundColorAndBorderColor = (args: AvatarBaseProps) => ( B { it('should render correctly', () => { @@ -17,11 +23,11 @@ describe('AvatarBase', () => { it('should render with different size classes', () => { const { getByTestId } = render( <> - - - - - + + + + + , ); expect(getByTestId('avatar-base-xs')).toHaveClass( @@ -84,11 +90,11 @@ describe('AvatarBase', () => { const { getByTestId } = render( <> , @@ -105,11 +111,11 @@ describe('AvatarBase', () => { const { getByTestId } = render( <> , @@ -121,4 +127,10 @@ describe('AvatarBase', () => { `box--border-color-${Color.errorDefault}`, ); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render(A); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/avatar-base/avatar-base.tsx b/ui/components/component-library/avatar-base/avatar-base.tsx new file mode 100644 index 000000000..e2dde6870 --- /dev/null +++ b/ui/components/component-library/avatar-base/avatar-base.tsx @@ -0,0 +1,63 @@ +import React, { forwardRef, Ref } from 'react'; +import classnames from 'classnames'; + +import { + BackgroundColor, + BorderColor, + TextColor, + DISPLAY, + JustifyContent, + AlignItems, + BorderRadius, + TextVariant, + TextTransform, +} from '../../../helpers/constants/design-system'; + +import { Text, ValidTag } from '../text'; + +import { AvatarBaseProps, AvatarBaseSize } from './avatar-base.types'; + +export const AvatarBase = forwardRef( + ( + { + size = AvatarBaseSize.Md, + children, + backgroundColor = BackgroundColor.backgroundAlternative, + borderColor = BorderColor.borderDefault, + color = TextColor.textDefault, + className = '', + ...props + }: AvatarBaseProps, + ref: Ref, + ) => { + let fallbackTextVariant; + + if (size === AvatarBaseSize.Lg || size === AvatarBaseSize.Xl) { + fallbackTextVariant = TextVariant.bodyLgMedium; + } else if (size === AvatarBaseSize.Sm || size === AvatarBaseSize.Md) { + fallbackTextVariant = TextVariant.bodySm; + } else { + fallbackTextVariant = TextVariant.bodyXs; + } + return ( + + {children} + + ); + }, +); diff --git a/ui/components/component-library/avatar-base/avatar-base.types.ts b/ui/components/component-library/avatar-base/avatar-base.types.ts new file mode 100644 index 000000000..11bc51ac7 --- /dev/null +++ b/ui/components/component-library/avatar-base/avatar-base.types.ts @@ -0,0 +1,47 @@ +import { + BackgroundColor, + BorderColor, + TextColor, +} from '../../../helpers/constants/design-system'; +import { TextProps } from '../text'; + +export enum AvatarBaseSize { + Xs = 'xs', + Sm = 'sm', + Md = 'md', + Lg = 'lg', + Xl = 'xl', +} + +export interface AvatarBaseProps extends TextProps { + /** + * The size of the AvatarBase. + * Possible values could be 'AvatarBaseSize.Xs'(16px), 'AvatarBaseSize.Sm'(24px), + * 'AvatarBaseSize.Md'(32px), 'AvatarBaseSize.Lg'(40px), 'AvatarBaseSize.Xl'(48px) + * Defaults to AvatarBaseSize.Md + */ + size?: AvatarBaseSize; + /** + * The children to be rendered inside the AvatarBase + */ + children: React.ReactNode; + /** + * The background color of the AvatarBase + * Defaults to Color.backgroundAlternative + */ + backgroundColor?: BackgroundColor; + /** + * The background color of the AvatarBase + * Defaults to Color.borderDefault + */ + borderColor?: BorderColor; + /** + * The color of the text inside the AvatarBase + * Defaults to TextColor.textDefault + */ + color?: TextColor; + /** + * Additional classNames to be added to the AvatarBase + */ + className?: string; +} diff --git a/ui/components/component-library/avatar-base/index.js b/ui/components/component-library/avatar-base/index.js deleted file mode 100644 index 5cd6109d9..000000000 --- a/ui/components/component-library/avatar-base/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { AvatarBase } from './avatar-base'; -export { AVATAR_BASE_SIZES } from './avatar-base.constants'; diff --git a/ui/components/component-library/avatar-base/index.ts b/ui/components/component-library/avatar-base/index.ts new file mode 100644 index 000000000..e1295f32a --- /dev/null +++ b/ui/components/component-library/avatar-base/index.ts @@ -0,0 +1,3 @@ +export { AvatarBase } from './avatar-base'; +export { AvatarBaseSize } from './avatar-base.types'; +export type { AvatarBaseProps } from './avatar-base.types'; diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.js b/ui/components/component-library/avatar-favicon/avatar-favicon.js index ab8607fa0..6f83d8587 100644 --- a/ui/components/component-library/avatar-favicon/avatar-favicon.js +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.js @@ -15,43 +15,48 @@ import { import { useI18nContext } from '../../../hooks/useI18nContext'; import { AVATAR_FAVICON_SIZES } from './avatar-favicon.constants'; -export const AvatarFavicon = ({ - size = Size.MD, - src, - name = 'avatar-favicon', - className, - fallbackIconProps, - borderColor = BorderColor.transparent, - ...props -}) => { - const t = useI18nContext(); - - return ( - - {src ? ( - {t('logo', - ) : ( - - )} - - ); -}; +export const AvatarFavicon = React.forwardRef( + ( + { + size = Size.MD, + src, + name = 'avatar-favicon', + className, + fallbackIconProps, + borderColor = BorderColor.transparent, + ...props + }, + ref, + ) => { + const t = useI18nContext(); + return ( + + {src ? ( + {t('logo', + ) : ( + + )} + + ); + }, +); AvatarFavicon.propTypes = { /** @@ -87,3 +92,5 @@ AvatarFavicon.propTypes = { */ ...Box.propTypes, }; + +AvatarFavicon.displayName = 'AvatarFavicon'; diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.test.js b/ui/components/component-library/avatar-favicon/avatar-favicon.test.js index 4c882f0c1..dd71aae8f 100644 --- a/ui/components/component-library/avatar-favicon/avatar-favicon.test.js +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.test.js @@ -105,4 +105,10 @@ describe('AvatarFavicon', () => { ); expect(getByTestId('classname')).toHaveClass('mm-avatar-favicon--test'); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render(); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/avatar-icon/avatar-icon.js b/ui/components/component-library/avatar-icon/avatar-icon.js index 53271ef5b..d3ce05f16 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.js +++ b/ui/components/component-library/avatar-icon/avatar-icon.js @@ -19,33 +19,39 @@ import { AvatarBase } from '../avatar-base'; import { AVATAR_ICON_SIZES } from './avatar-icon.constants'; -export const AvatarIcon = ({ - size = Size.MD, - color = TextColor.primaryDefault, - backgroundColor = BackgroundColor.primaryMuted, - className, - iconProps, - iconName, - ...props -}) => ( - - ( + - + display={DISPLAY.FLEX} + alignItems={AlignItems.center} + justifyContent={JustifyContent.center} + color={color} + backgroundColor={backgroundColor} + borderColor={BorderColor.transparent} + className={classnames('mm-avatar-icon', className)} + {...props} + > + + + ), ); AvatarIcon.propTypes = { @@ -87,3 +93,5 @@ AvatarIcon.propTypes = { */ ...Box.propTypes, }; + +AvatarIcon.displayName = 'AvatarIcon'; diff --git a/ui/components/component-library/avatar-icon/avatar-icon.test.js b/ui/components/component-library/avatar-icon/avatar-icon.test.js index 9b065d19b..e334dd81b 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.test.js +++ b/ui/components/component-library/avatar-icon/avatar-icon.test.js @@ -105,4 +105,10 @@ describe('AvatarIcon', () => { 'box--background-color-success-muted', ); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render(); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/avatar-network/avatar-network.js b/ui/components/component-library/avatar-network/avatar-network.js index f32001c52..cdc18025d 100644 --- a/ui/components/component-library/avatar-network/avatar-network.js +++ b/ui/components/component-library/avatar-network/avatar-network.js @@ -14,70 +14,76 @@ import { } from '../../../helpers/constants/design-system'; import { AVATAR_NETWORK_SIZES } from './avatar-network.constants'; -export const AvatarNetwork = ({ - size = Size.MD, - name, - src, - showHalo, - color = TextColor.textDefault, - backgroundColor = BackgroundColor.backgroundAlternative, - borderColor = BorderColor.transparent, - className, - ...props -}) => { - const [showFallback, setShowFallback] = useState(false); +export const AvatarNetwork = React.forwardRef( + ( + { + size = Size.MD, + name, + src, + showHalo, + color = TextColor.textDefault, + backgroundColor = BackgroundColor.backgroundAlternative, + borderColor = BorderColor.transparent, + className, + ...props + }, + ref, + ) => { + const [showFallback, setShowFallback] = useState(false); - useEffect(() => { - setShowFallback(!src); - }, [src]); + useEffect(() => { + setShowFallback(!src); + }, [src]); - const fallbackString = name && name[0] ? name[0] : '?'; + const fallbackString = name && name[0] ? name[0] : '?'; - const handleOnError = () => { - setShowFallback(true); - }; + const handleOnError = () => { + setShowFallback(true); + }; - return ( - - {showFallback ? ( - fallbackString - ) : ( - <> - {showHalo && ( + return ( + + {showFallback ? ( + fallbackString + ) : ( + <> + {showHalo && ( + + )} - )} - {`${name} - - )} - - ); -}; + + )} + + ); + }, +); AvatarNetwork.propTypes = { /** @@ -123,3 +129,5 @@ AvatarNetwork.propTypes = { */ ...Box.propTypes, }; + +AvatarNetwork.displayName = 'AvatarNetwork'; diff --git a/ui/components/component-library/avatar-network/avatar-network.test.js b/ui/components/component-library/avatar-network/avatar-network.test.js index 8817dc53e..4693c4e59 100644 --- a/ui/components/component-library/avatar-network/avatar-network.test.js +++ b/ui/components/component-library/avatar-network/avatar-network.test.js @@ -123,4 +123,10 @@ describe('AvatarNetwork', () => { `box--border-color-${BorderColor.errorDefault}`, ); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render(); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/avatar-token/avatar-token.js b/ui/components/component-library/avatar-token/avatar-token.js index cd0f47ad4..9cc951011 100644 --- a/ui/components/component-library/avatar-token/avatar-token.js +++ b/ui/components/component-library/avatar-token/avatar-token.js @@ -14,70 +14,76 @@ import { } from '../../../helpers/constants/design-system'; import { AVATAR_TOKEN_SIZES } from './avatar-token.constants'; -export const AvatarToken = ({ - size = Size.MD, - name, - src, - showHalo, - color = TextColor.textDefault, - backgroundColor = BackgroundColor.backgroundAlternative, - borderColor = BorderColor.transparent, - className, - ...props -}) => { - const [showFallback, setShowFallback] = useState(false); +export const AvatarToken = React.forwardRef( + ( + { + size = Size.MD, + name, + src, + showHalo, + color = TextColor.textDefault, + backgroundColor = BackgroundColor.backgroundAlternative, + borderColor = BorderColor.transparent, + className, + ...props + }, + ref, + ) => { + const [showFallback, setShowFallback] = useState(false); - useEffect(() => { - setShowFallback(!src); - }, [src]); + useEffect(() => { + setShowFallback(!src); + }, [src]); - const handleOnError = () => { - setShowFallback(true); - }; + const handleOnError = () => { + setShowFallback(true); + }; - const fallbackString = name && name[0] ? name[0] : '?'; + const fallbackString = name && name[0] ? name[0] : '?'; - return ( - - {showFallback ? ( - fallbackString - ) : ( - <> - {showHalo && ( + return ( + + {showFallback ? ( + fallbackString + ) : ( + <> + {showHalo && ( + + )} - )} - {`${name} - - )} - - ); -}; + + )} + + ); + }, +); AvatarToken.propTypes = { /** @@ -123,3 +129,5 @@ AvatarToken.propTypes = { */ ...Box.propTypes, }; + +AvatarToken.displayName = 'AvatarToken'; diff --git a/ui/components/component-library/avatar-token/avatar-token.test.js b/ui/components/component-library/avatar-token/avatar-token.test.js index 3a711782d..9fef751ca 100644 --- a/ui/components/component-library/avatar-token/avatar-token.test.js +++ b/ui/components/component-library/avatar-token/avatar-token.test.js @@ -121,4 +121,10 @@ describe('AvatarToken', () => { `box--border-color-${BorderColor.errorDefault}`, ); }); + it('should forward a ref to the root html element', () => { + const ref = React.createRef(); + render(); + expect(ref.current).not.toBeNull(); + expect(ref.current.nodeName).toBe('DIV'); + }); }); diff --git a/ui/components/component-library/button/README.mdx b/ui/components/component-library/button/README.mdx index 0e1527ff7..6b171cbdc 100644 --- a/ui/components/component-library/button/README.mdx +++ b/ui/components/component-library/button/README.mdx @@ -25,26 +25,26 @@ The `Button` accepts all [ButtonPrimary](/docs/components-componentlibrary-butto -### Type +### Variant -Use the `type` prop and the `BUTTON_TYPES` object from `./button.constants.js` to change the `Button` type. +Use the `variant` prop and the `BUTTON_VARIANT` object from `./button.constants.js` to change the `Button` variant. -Possible types include: +Possible variants include: -- `BUTTON_TYPES.PRIMARY` -- `BUTTON_TYPES.SECONDARY` -- `BUTTON_TYPES.LINK` +- `BUTTON_VARIANT.PRIMARY` +- `BUTTON_VARIANT.SECONDARY` +- `BUTTON_VARIANT.LINK` - + ```jsx -import { Button, BUTTON_TYPES } from '../ui/component-library/button'; +import { Button, BUTTON_VARIANT } from '../ui/component-library/button'; - - - + + + ``` ### Size diff --git a/ui/components/component-library/button/button.constants.js b/ui/components/component-library/button/button.constants.js index 4f5f6ef0f..b555bb11a 100644 --- a/ui/components/component-library/button/button.constants.js +++ b/ui/components/component-library/button/button.constants.js @@ -8,7 +8,7 @@ export const BUTTON_SIZES = { AUTO: Size.auto, }; -export const BUTTON_TYPES = { +export const BUTTON_VARIANT = { PRIMARY: 'primary', SECONDARY: 'secondary', LINK: 'link', diff --git a/ui/components/component-library/button/button.js b/ui/components/component-library/button/button.js index eaaa5486b..111a01458 100644 --- a/ui/components/component-library/button/button.js +++ b/ui/components/component-library/button/button.js @@ -5,15 +5,15 @@ import { ButtonPrimary } from '../button-primary'; import { ButtonSecondary } from '../button-secondary'; import { ButtonLink } from '../button-link'; -import { BUTTON_TYPES } from './button.constants'; +import { BUTTON_VARIANT } from './button.constants'; -export const Button = ({ type, ...props }) => { - switch (type) { - case BUTTON_TYPES.PRIMARY: +export const Button = ({ variant, ...props }) => { + switch (variant) { + case BUTTON_VARIANT.PRIMARY: return ; - case BUTTON_TYPES.SECONDARY: + case BUTTON_VARIANT.SECONDARY: return ; - case BUTTON_TYPES.LINK: + case BUTTON_VARIANT.LINK: return ; default: return ; @@ -22,11 +22,11 @@ export const Button = ({ type, ...props }) => { Button.propTypes = { /** - * Select the type of Button. - * Possible values could be 'BUTTON_TYPES.PRIMARY', 'BUTTON_TYPES.SECONDARY', 'BUTTON_TYPES.LINK' - * Button will default to `BUTTON_TYPES.PRIMARY` + * Select the variant of Button. + * Possible values could be 'BUTTON_VARIANT.PRIMARY', 'BUTTON_VARIANT.SECONDARY', 'BUTTON_VARIANT.LINK' + * Button will default to `BUTTON_VARIANT.PRIMARY` */ - type: PropTypes.oneOf(Object.values(BUTTON_TYPES)), + variant: PropTypes.oneOf(Object.values(BUTTON_VARIANT)), /** * Button accepts all the props from ButtonPrimary (same props as ButtonSecondary & ButtonLink) */ diff --git a/ui/components/component-library/button/button.stories.js b/ui/components/component-library/button/button.stories.js index e85d37fa6..bc2176611 100644 --- a/ui/components/component-library/button/button.stories.js +++ b/ui/components/component-library/button/button.stories.js @@ -11,7 +11,7 @@ import { BUTTON_LINK_SIZES } from '../button-link/button-link.constants'; import Box from '../../ui/box/box'; import { Text } from '../text'; import README from './README.mdx'; -import { Button, BUTTON_TYPES } from '.'; +import { Button, BUTTON_VARIANT } from '.'; const marginSizeControlOptions = [ undefined, @@ -85,8 +85,8 @@ export default { control: 'select', options: Object.values(BUTTON_LINK_SIZES), }, - type: { - options: Object.values(BUTTON_TYPES), + variant: { + options: Object.values(BUTTON_VARIANT), control: 'select', }, marginTop: { @@ -119,15 +119,15 @@ export const DefaultStory = (args) => - - @@ -150,12 +150,12 @@ export const SizeStory = (args) => ( - - {' '} inherits the font-size of the parent element. Inherit size only used for diff --git a/ui/components/component-library/button/button.test.js b/ui/components/component-library/button/button.test.js index 1fd245238..f612b4da6 100644 --- a/ui/components/component-library/button/button.test.js +++ b/ui/components/component-library/button/button.test.js @@ -2,7 +2,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { IconName } from '..'; -import { BUTTON_SIZES, BUTTON_TYPES } from './button.constants'; +import { BUTTON_SIZES, BUTTON_VARIANT } from './button.constants'; import { Button } from './button'; describe('Button', () => { @@ -46,28 +46,31 @@ describe('Button', () => { it('should render with different button types', () => { const { getByTestId, container } = render( <> - - + , ); - expect(getByTestId(BUTTON_TYPES.PRIMARY)).toHaveClass( - `mm-button-${BUTTON_TYPES.PRIMARY}`, + expect(getByTestId(BUTTON_VARIANT.PRIMARY)).toHaveClass( + `mm-button-${BUTTON_VARIANT.PRIMARY}`, ); - expect(getByTestId(BUTTON_TYPES.SECONDARY)).toHaveClass( - `mm-button-${BUTTON_TYPES.SECONDARY}`, + expect(getByTestId(BUTTON_VARIANT.SECONDARY)).toHaveClass( + `mm-button-${BUTTON_VARIANT.SECONDARY}`, ); - expect(getByTestId(BUTTON_TYPES.LINK)).toHaveClass( - `mm-button-${BUTTON_TYPES.LINK}`, + expect(getByTestId(BUTTON_VARIANT.LINK)).toHaveClass( + `mm-button-${BUTTON_VARIANT.LINK}`, ); expect(container).toMatchSnapshot(); }); @@ -77,7 +80,7 @@ describe('Button', () => { <> }> + StartAccessory +; +``` + +### endAccessory + +Use the `endAccessory` prop to render a component in the endAccessory position. This will override the default close `ButtonIcon`. + + + + + +```jsx +import { ModalHeader, Button, BUTTON_SIZES } from '../../component-library'; + +Demo}> + EndAccessory +; +``` diff --git a/ui/components/component-library/modal-header/__snapshots__/modal-header.test.tsx.snap b/ui/components/component-library/modal-header/__snapshots__/modal-header.test.tsx.snap new file mode 100644 index 000000000..d5c717bcf --- /dev/null +++ b/ui/components/component-library/modal-header/__snapshots__/modal-header.test.tsx.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ModalHeader should render ModalHeader correctly 1`] = ` +
+
+
+

+ Modal header +

+
+
+
+`; diff --git a/ui/components/component-library/modal-header/index.ts b/ui/components/component-library/modal-header/index.ts new file mode 100644 index 000000000..54a9313c0 --- /dev/null +++ b/ui/components/component-library/modal-header/index.ts @@ -0,0 +1,2 @@ +export { ModalHeader } from './modal-header'; +export type { ModalHeaderProps } from './modal-header.types'; diff --git a/ui/components/component-library/modal-header/modal-header.stories.tsx b/ui/components/component-library/modal-header/modal-header.stories.tsx new file mode 100644 index 000000000..525379dc9 --- /dev/null +++ b/ui/components/component-library/modal-header/modal-header.stories.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import { + TextVariant, + TextAlign, + DISPLAY, + FLEX_DIRECTION, + AlignItems, + JustifyContent, +} from '../../../helpers/constants/design-system'; + +import { AvatarAccount, BUTTON_SIZES, Button, Text } from '..'; + +import { ModalHeader } from './modal-header'; +import README from './README.mdx'; + +export default { + title: 'Components/ComponentLibrary/ModalHeader', + component: ModalHeader, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + children: { control: 'text' }, + className: { control: 'text' }, + onBack: { action: 'onBack' }, + onClose: { action: 'onClose' }, + }, + args: { + children: 'ModalHeader', + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => { + return ; +}; + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const Children: ComponentStory = (args) => ( + <> + + Children as string + + + + + Custom header using multiple components + + + +); + +export const OnBack = Template.bind({}); +OnBack.args = { + children: 'OnBack demo', +}; + +export const OnClose = Template.bind({}); +OnClose.args = { + children: 'OnClose demo', +}; + +export const StartAccessory = Template.bind({}); +StartAccessory.args = { + children: 'StartAccessory demo', + startAccessory: , +}; + +export const EndAccessory = Template.bind({}); +EndAccessory.args = { + children: 'EndAccessory demo', + endAccessory: , +}; diff --git a/ui/components/component-library/modal-header/modal-header.test.tsx b/ui/components/component-library/modal-header/modal-header.test.tsx new file mode 100644 index 000000000..00fb648b9 --- /dev/null +++ b/ui/components/component-library/modal-header/modal-header.test.tsx @@ -0,0 +1,67 @@ +/* eslint-disable jest/require-top-level-describe */ +import { render, fireEvent } from '@testing-library/react'; +import React from 'react'; +import { ModalHeader } from './modal-header'; + +describe('ModalHeader', () => { + it('should render ModalHeader correctly', () => { + const { getByTestId, container } = render( + Modal header, + ); + expect(getByTestId('modal-header')).toHaveClass('mm-modal-header'); + expect(container).toMatchSnapshot(); + }); + + it('should render modal header children as a string', () => { + const { getByText } = render( + Modal header test, + ); + expect(getByText('Modal header test')).toBeDefined(); + }); + + it('should render modal header children as a node', () => { + const { getByText, getByTestId } = render( + +
Modal header test
+
, + ); + expect(getByText('Modal header test')).toBeDefined(); + expect(getByTestId('div')).toBeDefined(); + }); + + it('should render modal header back button', () => { + const onBackTest = jest.fn(); + const { getByTestId } = render( + + ModalHeader + , + ); + + const backButton = getByTestId('back'); + fireEvent.click(backButton); + + expect(onBackTest).toHaveBeenCalled(); + }); + + it('should render modal header close button', () => { + const onCloseTest = jest.fn(); + const { getByTestId } = render( + + Modal header + , + ); + + const closeButton = getByTestId('close'); + fireEvent.click(closeButton); + + expect(onCloseTest).toHaveBeenCalled(); + }); +}); diff --git a/ui/components/component-library/modal-header/modal-header.tsx b/ui/components/component-library/modal-header/modal-header.tsx new file mode 100644 index 000000000..9cd4ca5d3 --- /dev/null +++ b/ui/components/component-library/modal-header/modal-header.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import classnames from 'classnames'; +import { HeaderBase, Text, ButtonIcon, ButtonIconSize, IconName } from '..'; +import { + TextVariant, + TextAlign, +} from '../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { ModalHeaderProps } from '.'; + +export const ModalHeader: React.FC = ({ + children, + className = '', + startAccessory, + endAccessory, + onClose, + closeButtonProps, + onBack, + backButtonProps, + ...props +}) => { + const t = useI18nContext(); + return ( + + )) + } + endAccessory={ + endAccessory || + (onClose && ( + + )) + } + {...props} + > + {typeof children === 'string' ? ( + + {children} + + ) : ( + children + )} + + ); +}; diff --git a/ui/components/component-library/modal-header/modal-header.types.ts b/ui/components/component-library/modal-header/modal-header.types.ts new file mode 100644 index 000000000..47bb752a0 --- /dev/null +++ b/ui/components/component-library/modal-header/modal-header.types.ts @@ -0,0 +1,42 @@ +import React from 'react'; +import type { ButtonIconProps } from '../button-icon/button-icon.types'; +import type { HeaderBaseProps } from '../header-base'; + +export interface ModalHeaderProps extends HeaderBaseProps { + /** + * The contents within the ModalHeader positioned middle (popular for title use case) + */ + children?: React.ReactNode; + /** + * Additional classNames to be added to the ModalHeader component + */ + className?: string; + /** + * The onClick handler for the back `ButtonIcon` + * When passed this will allow for the back `ButtonIcon` to show + */ + onBack?: () => void; + /** + * The props to pass to the back `ButtonIcon` + */ + backButtonProps?: ButtonIconProps; + /** + * The start (left) content area of ModalHeader + * Default to have the back `ButtonIcon` when `onBack` is passed, but passing a `startAccessory` will override this + */ + startAccessory?: React.ReactNode; + /** + * The onClick handler for the close `ButtonIcon` + * When passed this will allow for the close `ButtonIcon` to show + */ + onClose?: () => void; + /** + * The props to pass to the close `ButtonIcon` + */ + closeButtonProps?: ButtonIconProps; + /** + * The end (right) content area of ModalHeader + * Default to have the close `ButtonIcon` when `onClose` is passed, but passing a `endAccessory` will override this + */ + endAccessory?: React.ReactNode; +} diff --git a/ui/components/component-library/picker-network/README.mdx b/ui/components/component-library/picker-network/README.mdx index 1470619c2..2d7185d99 100644 --- a/ui/components/component-library/picker-network/README.mdx +++ b/ui/components/component-library/picker-network/README.mdx @@ -18,7 +18,7 @@ The `PickerNetwork` accepts all props below as well as all [Box](/docs/component ### Label -Use the `label` prop for the text content of the `PickerNetwork` component +Use the `label` prop for the text content of the `PickerNetwork` component. For long labels set a `max-width` using a `className` and the text will truncate showing an ellipsis. @@ -29,6 +29,7 @@ import { PickerNetwork } from '../../ui/component-library'; + ``` ### Src @@ -44,4 +45,4 @@ import { PickerNetwork } from '../../ui/component-library'; -``` \ No newline at end of file +``` diff --git a/ui/components/component-library/picker-network/picker-network.stories.js b/ui/components/component-library/picker-network/picker-network.stories.js index 8e4865102..650f2866f 100644 --- a/ui/components/component-library/picker-network/picker-network.stories.js +++ b/ui/components/component-library/picker-network/picker-network.stories.js @@ -38,6 +38,11 @@ export const Label = (args) => ( + ); diff --git a/ui/components/component-library/popover-header/README.mdx b/ui/components/component-library/popover-header/README.mdx index 6910ec10c..0680c2b6a 100644 --- a/ui/components/component-library/popover-header/README.mdx +++ b/ui/components/component-library/popover-header/README.mdx @@ -3,7 +3,7 @@ import { PopoverHeader } from './popover-header'; # PopoverHeader -PopoverHeader is built on top of [HeaderBase](/docs/components-componentlibrary-headerbase--default-story) component with the most common use case of a back button in the startAccessory position, title, and close button in the endAccessory position. +`PopoverHeader` handles the title, close button and back button for all `Popover` components. It is built on top of the [HeaderBase](/docs/components-componentlibrary-headerbase--default-story) component @@ -17,16 +17,41 @@ The `PopoverHeader` accepts all props below as well as all [Box](/docs/ui-compon ### Children -Wrapping string content in the `PopoverHeader` component will be rendered in the center of the header with the default title `Text` component. +The title of the `PopoverHeader` component. Passing a `string` will render the content inside of a `Text` component. Passing any other type will render the content as is. ```jsx -import { PopoverHeader } from '../../component-library'; +import { + TextVariant, + TextAlign, + DISPLAY, + FLEX_DIRECTION, + AlignItems, + JustifyContent, +} from '../../../helpers/constants/design-system'; -Title is sentence case no period; +import { PopoverHeader, AvatarAccount, Text } from '../../component-library'; + + + Children as string + + + + + Custom header using multiple components + + ``` ### onBack diff --git a/ui/components/component-library/popover-header/__snapshots__/popover-header.test.tsx.snap b/ui/components/component-library/popover-header/__snapshots__/popover-header.test.tsx.snap index ff2a28597..d6bd840f2 100644 --- a/ui/components/component-library/popover-header/__snapshots__/popover-header.test.tsx.snap +++ b/ui/components/component-library/popover-header/__snapshots__/popover-header.test.tsx.snap @@ -7,12 +7,12 @@ exports[`PopoverHeader should render PopoverHeader correctly 1`] = ` data-testid="popover-header" >

- Popover Header + PopoverHeader

diff --git a/ui/components/component-library/popover-header/popover-header.stories.tsx b/ui/components/component-library/popover-header/popover-header.stories.tsx index a5f5d175d..92c188d81 100644 --- a/ui/components/component-library/popover-header/popover-header.stories.tsx +++ b/ui/components/component-library/popover-header/popover-header.stories.tsx @@ -1,6 +1,17 @@ import React from 'react'; import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { BUTTON_SIZES, Button } from '..'; + +import { + TextVariant, + TextAlign, + DISPLAY, + FLEX_DIRECTION, + AlignItems, + JustifyContent, +} from '../../../helpers/constants/design-system'; + +import { AvatarAccount, BUTTON_SIZES, Button, Text } from '..'; + import { PopoverHeader } from './popover-header'; import README from './README.mdx'; @@ -24,42 +35,52 @@ export default { } as ComponentMeta; const Template: ComponentStory = (args) => { - return PopoverHeader; + return ; }; export const DefaultStory = Template.bind({}); DefaultStory.storyName = 'Default'; export const Children: ComponentStory = (args) => ( - + <> + + Children as string + + + + + Custom header using multiple components + + + ); -Children.args = { - children: 'PopoverHeader Title', +export const OnBack = Template.bind({}); +OnBack.args = { + children: 'OnBack demo', }; -export const OnBack: ComponentStory = (args) => ( - OnBack Demo -); +export const OnClose = Template.bind({}); +OnClose.args = { + children: 'OnClose demo', +}; -export const OnClose: ComponentStory = (args) => ( - OnClose Demo -); +export const StartAccessory = Template.bind({}); +StartAccessory.args = { + children: 'StartAccessory demo', + startAccessory: , +}; -export const StartAccessory: ComponentStory = (args) => ( - Demo} - {...args} - > - StartAccessory - -); - -export const EndAccessory: ComponentStory = (args) => ( - Demo} - {...args} - > - EndAccessory - -); +export const EndAccessory = Template.bind({}); +EndAccessory.args = { + children: 'EndAccessory demo', + endAccessory: , +}; diff --git a/ui/components/component-library/popover-header/popover-header.test.tsx b/ui/components/component-library/popover-header/popover-header.test.tsx index ec5e4e203..8918ed6f0 100644 --- a/ui/components/component-library/popover-header/popover-header.test.tsx +++ b/ui/components/component-library/popover-header/popover-header.test.tsx @@ -6,32 +6,39 @@ import { PopoverHeader } from './popover-header'; describe('PopoverHeader', () => { it('should render PopoverHeader correctly', () => { const { getByTestId, container } = render( - - Popover Header - , + PopoverHeader, ); expect(getByTestId('popover-header')).toHaveClass('mm-popover-header'); expect(container).toMatchSnapshot(); }); - it('should render popover header title', () => { + it('should render popover header children as a string', () => { const { getByText } = render( - Popover Header Test + PopoverHeader test , ); - expect(getByText('Popover Header Test')).toBeDefined(); + expect(getByText('PopoverHeader test')).toBeDefined(); + }); + + it('should render popover header children as a node', () => { + const { getByText, getByTestId } = render( + +
PopoverHeader test
+
, + ); + expect(getByText('PopoverHeader test')).toBeDefined(); + expect(getByTestId('div')).toBeDefined(); }); it('should render popover header back button', () => { const onBackTest = jest.fn(); const { getByTestId } = render( - Popover + PopoverHeader , ); @@ -45,11 +52,10 @@ describe('PopoverHeader', () => { const onCloseTest = jest.fn(); const { getByTestId } = render( - Popover + PopoverHeader , ); diff --git a/ui/components/component-library/popover-header/popover-header.types.ts b/ui/components/component-library/popover-header/popover-header.types.ts index 66f8c7379..a965dbd54 100644 --- a/ui/components/component-library/popover-header/popover-header.types.ts +++ b/ui/components/component-library/popover-header/popover-header.types.ts @@ -8,7 +8,7 @@ export interface PopoverHeaderProps extends HeaderBaseProps { */ children?: React.ReactNode; /** - * Additional classNames to be added to the Popover component + * Additional classNames to be added to the PopoverHeader component */ className?: string; /** diff --git a/ui/components/component-library/text/README.mdx b/ui/components/component-library/text/README.mdx index 0aa0499a3..3ca145b4d 100644 --- a/ui/components/component-library/text/README.mdx +++ b/ui/components/component-library/text/README.mdx @@ -335,6 +335,25 @@ import { Text, TextDirection } from '../../component-library'; ``` +### Strong + +Using the `as` prop with the value of `strong` will render the `Text` component as a `strong` element and any `strong` emlements used within a `Text` component will be supported with bold styles. + + + + + +```jsx +import { Text } from '../../component-library'; + + + This is an as="strong" demo. + + + This is a strong element demo. + +``` + ### Box Props Use any valid box props [Box](/?path=/story/components-ui-box--default-story) component props to the Text component. diff --git a/ui/components/component-library/text/text.scss b/ui/components/component-library/text/text.scss index da77a1f19..b6331d7e3 100644 --- a/ui/components/component-library/text/text.scss +++ b/ui/components/component-library/text/text.scss @@ -33,6 +33,10 @@ $text-variants: ( color: var(--color-text-default); font-family: var(--font-family-sans); + > strong { + font-weight: var(--font-weight-bold); + } + @each $type, $size-options in $text-variants { &--#{$type} { // Sets a default diff --git a/ui/components/component-library/text/text.stories.tsx b/ui/components/component-library/text/text.stories.tsx index be82bdb2a..3ece16787 100644 --- a/ui/components/component-library/text/text.stories.tsx +++ b/ui/components/component-library/text/text.stories.tsx @@ -4,12 +4,12 @@ import { DISPLAY, BackgroundColor, BorderColor, - FONT_WEIGHT, - FONT_STYLE, + FontWeight, + FontStyle, TextColor, - TEXT_ALIGN, - OVERFLOW_WRAP, - TEXT_TRANSFORM, + TextAlign, + OverflowWrap, + TextTransform, FRACTIONS, FLEX_DIRECTION, TextVariant, @@ -113,9 +113,9 @@ export const ColorStory: ComponentStory = (args) => { }; ColorStory.storyName = 'Color'; -export const FontWeight: ComponentStory = (args) => ( +export const FontWeightStory: ComponentStory = (args) => ( <> - {Object.values(FONT_WEIGHT).map((weight) => ( + {Object.values(FontWeight).map((weight) => ( {weight} @@ -123,9 +123,11 @@ export const FontWeight: ComponentStory = (args) => ( ); -export const FontStyle: ComponentStory = (args) => ( +FontWeightStory.storyName = 'Font Weight'; + +export const FontStyleStory: ComponentStory = (args) => ( <> - {Object.values(FONT_STYLE).map((style) => ( + {Object.values(FontStyle).map((style) => ( {style} @@ -133,9 +135,11 @@ export const FontStyle: ComponentStory = (args) => ( ); -export const TextTransform: ComponentStory = (args) => ( +FontStyleStory.storyName = 'Font Style'; + +export const TextTransformStory: ComponentStory = (args) => ( <> - {Object.values(TEXT_TRANSFORM).map((transform) => ( + {Object.values(TextTransform).map((transform) => ( {transform} @@ -143,9 +147,11 @@ export const TextTransform: ComponentStory = (args) => ( ); -export const TextAlign: ComponentStory = (args) => ( +TextTransformStory.storyName = 'Text Transform'; + +export const TextAlignStory: ComponentStory = (args) => ( <> - {Object.values(TEXT_ALIGN).map((align) => ( + {Object.values(TextAlign).map((align) => ( {align} @@ -153,21 +159,25 @@ export const TextAlign: ComponentStory = (args) => ( ); -export const OverflowWrap: ComponentStory = (args) => ( +TextAlignStory.storyName = 'Text Align'; + +export const OverflowWrapStory: ComponentStory = (args) => ( - - {OVERFLOW_WRAP.NORMAL}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d + + {OverflowWrap.Normal}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d - - {OVERFLOW_WRAP.BREAK_WORD}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d + + {OverflowWrap.BreakWord}: 0x39013f961c378f02c2b82a6e1d31e9812786fd9d ); +OverflowWrapStory.storyName = 'Overflow Wrap'; + export const Ellipsis: ComponentStory = (args) => ( = (args) => ( ); + +export const Strong: ComponentStory = (args) => ( + <> + + This is an as="strong" demo. + + + This is a strong element demo. + + +); diff --git a/ui/components/institutional/compliance-details/__snapshots__/compliance-details.test.js.snap b/ui/components/institutional/compliance-details/__snapshots__/compliance-details.test.js.snap new file mode 100644 index 000000000..2cd5c29ec --- /dev/null +++ b/ui/components/institutional/compliance-details/__snapshots__/compliance-details.test.js.snap @@ -0,0 +1,144 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ComplianceDetails should render correctly 1`] = ` +
+
+
+

+ Address +

+

+ 0xAddress +

+
+
+
+

+ Risk rating +

+
+
+
+ + + +
+
+
+
+
+

+ low +

+
+
+
+
+

+ Report last run +

+
+
+
+ + + +
+
+
+
+

+

+
+ +
+
+
+`; diff --git a/ui/components/institutional/compliance-details/compliance-details.js b/ui/components/institutional/compliance-details/compliance-details.js new file mode 100644 index 000000000..c195dbd3c --- /dev/null +++ b/ui/components/institutional/compliance-details/compliance-details.js @@ -0,0 +1,159 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { I18nContext } from '../../../contexts/i18n'; +import InfoTooltip from '../../ui/info-tooltip'; +import SwapsFooter from '../../../pages/swaps/swaps-footer'; +import { + fetchHistoricalReports, + getComplianceHistoricalReportsByAddress, + getComplianceTenantSubdomain, +} from '../../../ducks/institutional/institutional'; +import { formatDate } from '../../../helpers/utils/util'; +import Box from '../../ui/box'; +import { Text } from '../../component-library'; +import { + TextColor, + TextVariant, + JustifyContent, + AlignItems, + BLOCK_SIZES, + DISPLAY, + FLEX_DIRECTION, +} from '../../../helpers/constants/design-system'; + +const ComplianceDetails = ({ address, onClose, onGenerate }) => { + const t = useContext(I18nContext); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(fetchHistoricalReports(address)); + }, [address, dispatch]); + + const [lastReport, setLastReport] = useState(null); + const historicalReports = useSelector( + getComplianceHistoricalReportsByAddress(address), + ); + + useEffect(() => { + if (historicalReports && historicalReports.length) { + setLastReport( + historicalReports.reduce((prev, cur) => + prev.createTime > cur.createTime ? prev : cur, + ), + ); + } + }, [historicalReports]); + + const complianceTenantSubdomain = useSelector(getComplianceTenantSubdomain); + + return ( + + + {t('address')} + {address} + + + + {t('riskRating')} + {t('riskRatingTooltip')}} + /> + + + {lastReport ? lastReport.risk : t('noReport')} + + + + + {t('reportLastRun')} + {t('reportLastRunTooltip')}} + /> + + + {lastReport + ? formatDate(new Date(lastReport.createTime).getTime()) + : 'N/A'} + + + + { + onGenerate(address); + onClose(); + }} + submitText={t('runReport')} + onCancel={() => + global.platform.openTab({ + url: `https://${complianceTenantSubdomain}.compliance.codefi.network/app/kyt/addresses/${lastReport.address}/${lastReport.reportId}`, + }) + } + cancelText={t('showReport')} + hideCancel={!lastReport} + approveActive={lastReport} + showTopBorder + /> + + + ); +}; + +ComplianceDetails.propTypes = { + address: PropTypes.string, + onClose: PropTypes.func, + onGenerate: PropTypes.func, +}; + +export default ComplianceDetails; diff --git a/ui/components/institutional/compliance-details/compliance-details.stories.js b/ui/components/institutional/compliance-details/compliance-details.stories.js new file mode 100644 index 000000000..b4ead4450 --- /dev/null +++ b/ui/components/institutional/compliance-details/compliance-details.stories.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import ComplianceDetails from '.'; + +const customData = { + ...testData, + metamask: { + institutionalFeatures: { + complianceProjectId: '', + complianceClientId: '', + reportsInProgress: {}, + historicalReports: { + '0xAddress': [ + { + reportId: 'reportId', + address: '0xAddress', + risk: 'low', + creatTime: new Date(), + }, + ], + }, + }, + }, +}; + +const store = configureStore(customData); + +export default { + title: 'Components/Institutional/ComplianceDetails', + decorators: [(story) => {story()}], + component: ComplianceDetails, + args: { + address: '0xAddress', + onClose: () => undefined, + onGenerate: () => undefined, + }, + argTypes: { + onClick: { + action: 'onClick', + }, + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'ComplianceDetails'; diff --git a/ui/components/institutional/compliance-details/compliance-details.test.js b/ui/components/institutional/compliance-details/compliance-details.test.js new file mode 100644 index 000000000..670d8a1b4 --- /dev/null +++ b/ui/components/institutional/compliance-details/compliance-details.test.js @@ -0,0 +1,67 @@ +import React from 'react'; +import configureStore from 'redux-mock-store'; +import { fireEvent, screen } from '@testing-library/react'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import ComplianceDetails from './compliance-details'; + +const initState = { + metamask: { + institutionalFeatures: { + complianceProjectId: '', + complianceClientId: '', + reportsInProgress: {}, + historicalReports: { + '0xAddress': [ + { + reportId: 'reportId', + address: '0xAddress', + risk: 'low', + creatTime: new Date(), + }, + ], + }, + }, + }, +}; +const middlewares = [thunk]; +const mockStore = configureStore(middlewares); + +describe('ComplianceDetails', () => { + const props = { + address: '0xAddress', + onClose: jest.fn(), + onGenerate: jest.fn(), + }; + + const store = mockStore(initState); + + it('should render correctly', () => { + const { container } = renderWithProvider( + , + store, + ); + + expect(container).toMatchSnapshot(); + }); + + it('runs onGenerate fuction', () => { + renderWithProvider( + , + store, + ); + + fireEvent.click(screen.queryByTestId('page-container-footer-next')); + + expect(props.onGenerate).toHaveBeenCalledTimes(1); + expect(props.onGenerate).toHaveBeenCalledWith(props.address); + }); +}); diff --git a/ui/components/institutional/compliance-details/index.js b/ui/components/institutional/compliance-details/index.js new file mode 100644 index 000000000..4cccdb1cd --- /dev/null +++ b/ui/components/institutional/compliance-details/index.js @@ -0,0 +1 @@ +export { default } from './compliance-details'; diff --git a/ui/components/institutional/compliance-details/index.scss b/ui/components/institutional/compliance-details/index.scss new file mode 100644 index 000000000..d342c36ff --- /dev/null +++ b/ui/components/institutional/compliance-details/index.scss @@ -0,0 +1,5 @@ +.compliance-details { + &__row { + border-top: 1px solid var(--color-border-muted); + } +} diff --git a/ui/components/institutional/compliance-settings/compliance-settings.js b/ui/components/institutional/compliance-settings/compliance-settings.js index 4289250c8..73aa65401 100644 --- a/ui/components/institutional/compliance-settings/compliance-settings.js +++ b/ui/components/institutional/compliance-settings/compliance-settings.js @@ -14,7 +14,7 @@ import { mmiActionsFactory } from '../../../store/institutional/institution-back import { Text, Button, - BUTTON_TYPES, + BUTTON_VARIANT, BUTTON_SIZES, } from '../../component-library'; import Box from '../../ui/box'; @@ -30,7 +30,7 @@ const ComplianceSettings = () => { const linkButton = ( +
+ + + +
+
+ + + + + + + + + +`; diff --git a/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js new file mode 100644 index 000000000..b59f12538 --- /dev/null +++ b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.js @@ -0,0 +1,125 @@ +import React, { memo, useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { useDispatch } from 'react-redux'; +import Modal from '../../app/modal'; +import CustodyAccountList from '../../../pages/institutional/connect-custody/account-list'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { removeAccount } from '../../../store/actions'; +import withModalProps from '../../../helpers/higher-order-components/with-modal-props'; +import { Text } from '../../component-library'; +import Box from '../../ui/box'; +import { + BorderRadius, + DISPLAY, + TEXT_ALIGN, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; + +const ConfirmRemoveJWT = ({ + custodyAccountDetails, + accounts, + token, + hideModal, +}) => { + const t = useI18nContext(); + const dispatch = useDispatch(); + const [showMore, setShowMore] = useState(false); + const [tokenAccounts, setTokenAccounts] = useState([]); + + useEffect(() => { + const lowercasedTokenAddress = token.address.toLowerCase(); + + const filteredAccounts = custodyAccountDetails.filter((item) => { + const addressLower = item.address.toLowerCase(); + return accounts.find((acc) => acc.address.toLowerCase() === addressLower); + }); + + const tokens = filteredAccounts + .filter(({ authDetails }) => { + const getToken = + authDetails?.token ?? authDetails?.jwt ?? authDetails?.refreshToken; + return getToken?.toLowerCase() === lowercasedTokenAddress; + }) + .map(({ address, name, labels, authDetails }) => { + const lowercasedAddress = address.toLowerCase(); + const account = accounts.find( + ({ address: adressAcc }) => + adressAcc.toLowerCase() === lowercasedAddress, + ); + const balance = account?.balance; + const getToken = + authDetails?.token ?? authDetails?.jwt ?? authDetails?.refreshToken; + return { address, name, labels, balance, token: getToken }; + }); + + setTokenAccounts(tokens); + }, [accounts, custodyAccountDetails, token]); + + const handleRemove = async () => { + try { + for (const account of tokenAccounts) { + await dispatch(removeAccount(account.address.toLowerCase())); + } + hideModal(); + } catch (error) { + console.error(error); + } + }; + + const handleShowMore = () => { + setShowMore(true); + }; + + return ( + + + {showMore && token ? token.address : `...${token.address.slice(-9)}`} + + {!showMore && ( + + + {t('showMore')} + + + )} + + {t('removeJWTDescription')} + + + + + + ); +}; + +ConfirmRemoveJWT.propTypes = { + hideModal: PropTypes.func.isRequired, + token: PropTypes.object.isRequired, + custodyAccountDetails: PropTypes.array.isRequired, + accounts: PropTypes.array.isRequired, +}; + +export default withModalProps(memo(ConfirmRemoveJWT)); diff --git a/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.stories.js b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.stories.js new file mode 100644 index 000000000..ae5590c14 --- /dev/null +++ b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.stories.js @@ -0,0 +1,31 @@ +import React from 'react'; +import ConfirmRemoveJWT from '.'; + +export default { + title: 'Components/Institutional/ConfirmRemoveJWT', + component: ConfirmRemoveJWT, + args: { + hideModal: () => { + /**/ + }, + removeAccount: () => { + /**/ + }, + token: { address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D' }, + custodyAccountDetails: [ + { + address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D', + name: 'Test name account', + labels: [], + authDetails: { token: '0xaD6D458402F60fD3Bd25163575031ACDce07538D' }, + }, + ], + accounts: [ + { address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D', balance: '0x0' }, + ], + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'ConfirmRemoveJWT'; diff --git a/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.test.js b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.test.js new file mode 100644 index 000000000..4416ede93 --- /dev/null +++ b/ui/components/institutional/confirm-remove-jwt-modal/confirm-remove-jwt-modal.test.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { fireEvent, waitFor } from '@testing-library/react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import testData from '../../../../.storybook/test-data'; +import ConfirmRemoveJwt from '.'; + +const mockedRemoveAccount = jest.fn(); +const mockedHideModal = jest.fn(); + +jest.mock('../../../store/actions', () => ({ + removeAccount: () => mockedRemoveAccount, + hideModal: () => mockedHideModal, +})); + +const address = '0xaD6D458402F60fD3Bd25163575031ACDce07538D'; + +const props = { + hideModal: mockedHideModal, + token: { address }, + custodyAccountDetails: [ + { + address, + name: 'Test name account', + labels: [], + authDetails: { token: address }, + }, + ], + accounts: [{ address, balance: '0x0' }], +}; + +const mockStore = { + ...testData, + metamask: {}, +}; + +const middleware = [thunk]; +const store = configureMockStore(middleware)(mockStore); + +const render = () => { + return renderWithProvider(, store); +}; + +describe('Confirm Remove JWT', function () { + it('should render correctly', () => { + const { container } = render(); + + expect(container).toMatchSnapshot(); + }); + + it('should show full token address when "show more" is clicked', () => { + const { getByText } = render(); + + const showMoreLink = getByText('Show more'); + fireEvent.click(showMoreLink); + + const fullTokenAddress = getByText(address); + expect(fullTokenAddress).toBeInTheDocument(); + }); + + it('dispatches removeAccount action when user clicks remove button', async () => { + const { getByText } = render(); + + const removeButton = getByText('Remove'); + fireEvent.click(removeButton); + + await waitFor(() => expect(mockedRemoveAccount).toHaveBeenCalled()); + expect(mockedHideModal).toHaveBeenCalled(); + }); +}); diff --git a/ui/components/institutional/confirm-remove-jwt-modal/index.js b/ui/components/institutional/confirm-remove-jwt-modal/index.js new file mode 100644 index 000000000..3f27ef6b4 --- /dev/null +++ b/ui/components/institutional/confirm-remove-jwt-modal/index.js @@ -0,0 +1 @@ +export { default } from './confirm-remove-jwt-modal'; diff --git a/ui/components/institutional/confirm-remove-jwt-modal/index.scss b/ui/components/institutional/confirm-remove-jwt-modal/index.scss new file mode 100644 index 000000000..1aff21359 --- /dev/null +++ b/ui/components/institutional/confirm-remove-jwt-modal/index.scss @@ -0,0 +1,13 @@ +.confirm-action-jwt { + &__jwt { + border: 1px solid var(--color-border-muted); + } + + &__show-more { + cursor: pointer; + } + + &__accounts-list { + margin-left: -5%; + } +} diff --git a/ui/components/institutional/custody-confirm-link-modal/__snapshots__/custody-confirm-link-modal.test.js.snap b/ui/components/institutional/custody-confirm-link-modal/__snapshots__/custody-confirm-link-modal.test.js.snap new file mode 100644 index 000000000..635f0371e --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/__snapshots__/custody-confirm-link-modal.test.js.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Custody Confirm Link should match snapshot 1`] = ` +
+
+
+ MMI logo + > + saturn-dev +
+

+ Awaiting approval... +

+ + +
+
+`; diff --git a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js new file mode 100644 index 000000000..36e1ef821 --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.js @@ -0,0 +1,135 @@ +import React, { useContext } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + MetaMetricsEventName, + MetaMetricsEventCategory, +} from '../../../../shared/constants/metametrics'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import withModalProps from '../../../helpers/higher-order-components/with-modal-props'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; +import { mmiActionsFactory } from '../../../store/institutional/institution-background'; +import { hideModal, setSelectedAddress } from '../../../store/actions'; +import { getMetaMaskAccountsRaw } from '../../../selectors'; +import { + getMMIAddressFromModalOrAddress, + getCustodyAccountDetails, + getMMIConfiguration, +} from '../../../selectors/institutional/selectors'; +import Box from '../../ui/box/box'; +import { + AlignItems, + DISPLAY, + FLEX_DIRECTION, + FontWeight, + JustifyContent, + TextAlign, + TextColor, + TextVariant, +} from '../../../helpers/constants/design-system'; +import { Text, Button, BUTTON_VARIANT } from '../../component-library'; + +const CustodyConfirmLink = () => { + const t = useI18nContext(); + const dispatch = useDispatch(); + const mmiActions = mmiActionsFactory(); + const trackEvent = useContext(MetaMetricsContext); + const mmiAccounts = useSelector(getMetaMaskAccountsRaw); + const address = useSelector(getMMIAddressFromModalOrAddress); + const custodyAccountDetails = useSelector(getCustodyAccountDetails); + const { custodians } = useSelector(getMMIConfiguration); + const { custodianName } = + custodyAccountDetails[toChecksumHexAddress(address)] || {}; + const { displayName, iconUrl } = custodians.find( + (item) => item.name === custodianName || {}, + ); + const { url, ethereum, text, action } = useSelector( + (state) => state.appState.modal.modalState.props.link || {}, + ); + + const onClick = () => { + if (url) { + global.platform.openTab({ url }); + } + + if (ethereum) { + const ethAccount = Object.keys(mmiAccounts).find((account) => + ethereum.accounts.includes(account.toLowerCase()), + ); + + ethAccount && dispatch(setSelectedAddress(ethAccount.toLowerCase())); + } + + trackEvent({ + category: MetaMetricsEventCategory.MMI, + event: MetaMetricsEventName.UserClickedDeepLink, + }); + dispatch(mmiActions.setWaitForConfirmDeepLinkDialog(false)); + dispatch(hideModal()); + }; + + return ( + + {iconUrl ? ( + + MMI logo + {'>'} + {custodianName} + + ) : ( + + {custodianName} + + )} + + {t('awaitingApproval')} + + + {text || t('custodyDeeplinkDescription', [displayName])} + + + + ); +}; + +export default withModalProps(CustodyConfirmLink); diff --git a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.stories.js b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.stories.js new file mode 100644 index 000000000..b735b9dd9 --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.stories.js @@ -0,0 +1,73 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import CustodyConfirmLink from '.'; + +const customData = { + ...testData, + appState: { + ...testData.appState, + modal: { + modalState: { + props: { + link: { + url: 'test-url', + ethereum: { + accounts: [{}], + }, + text: '', + action: '', + }, + }, + }, + }, + }, + metamask: { + ...testData.metamask, + mmiConfiguration: { + custodians: [ + { + refreshTokenUrl: + 'https://saturn-custody.dev.metamask-institutional.io/oauth/token', + name: 'saturn-dev', + displayName: 'Saturn Custody', + enabled: true, + mmiApiUrl: 'https://api.dev.metamask-institutional.io/v1', + websocketApiUrl: + 'wss://websocket.dev.metamask-institutional.io/v1/ws', + apiBaseUrl: + 'https://saturn-custody.dev.metamask-institutional.io/eth', + iconUrl: + 'https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg', + isNoteToTraderSupported: true, + }, + ], + }, + custodyAccountDetails: { + '0xAddress': { + address: '0xAddress', + details: 'details', + custodyType: 'testCustody - Saturn', + custodianName: 'saturn-dev', + }, + }, + providerConfig: { + type: 'test', + }, + selectedAddress: '0xAddress', + }, +}; + +const store = configureStore(customData); + +export default { + title: 'Components/Institutional/CustodyConfirmLink', + decorators: [(story) => {story()}], + component: CustodyConfirmLink, + args: {}, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'CustodyConfirmLink'; diff --git a/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.test.js b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.test.js new file mode 100644 index 000000000..a82ec7283 --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/custody-confirm-link-modal.test.js @@ -0,0 +1,192 @@ +import React from 'react'; +import { fireEvent } from '@testing-library/react'; +import configureStore from 'redux-mock-store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import testData from '../../../../.storybook/test-data'; +import { hideModal } from '../../../store/actions'; +import CustodyConfirmLink from '.'; + +const mockedSetWaitForConfirmDeepLinkDialog = jest + .fn() + .mockReturnValue({ type: 'TYPE' }); +jest.mock('../../../store/institutional/institution-background', () => ({ + mmiActionsFactory: () => ({ + setWaitForConfirmDeepLinkDialog: mockedSetWaitForConfirmDeepLinkDialog, + }), +})); + +jest.mock('../../../store/actions', () => ({ + hideModal: jest.fn().mockReturnValue({ type: 'TYPE' }), +})); + +const mockedCustodianName = 'saturn-dev'; + +describe('Custody Confirm Link', () => { + const mockStore = { + ...testData, + appState: { + ...testData.appState, + modal: { + modalState: { + props: { + link: { + url: 'test-url', + ethereum: { + accounts: [{}], + }, + text: '', + action: '', + }, + }, + }, + }, + }, + metamask: { + ...testData.metamask, + mmiConfiguration: { + custodians: [ + { + refreshTokenUrl: + 'https://saturn-custody.dev.metamask-institutional.io/oauth/token', + name: 'saturn-dev', + displayName: 'Saturn Custody', + enabled: true, + mmiApiUrl: 'https://api.dev.metamask-institutional.io/v1', + websocketApiUrl: + 'wss://websocket.dev.metamask-institutional.io/v1/ws', + apiBaseUrl: + 'https://saturn-custody.dev.metamask-institutional.io/eth', + iconUrl: + 'https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg', + isNoteToTraderSupported: true, + }, + ], + }, + custodyAccountDetails: { + '0xAddress': { + address: '0xAddress', + details: 'details', + custodyType: 'testCustody - Saturn', + custodianName: mockedCustodianName, + }, + }, + providerConfig: { + type: 'test', + }, + selectedAddress: '0xAddress', + }, + }; + + let store = configureStore()(mockStore); + + it('tries to open new tab with deeplink URL', () => { + global.platform = { openTab: jest.fn() }; + const { getByRole } = renderWithProvider(, store); + fireEvent.click(getByRole('button')); + expect(global.platform.openTab).toHaveBeenCalledWith({ + url: 'test-url', + }); + expect(mockedSetWaitForConfirmDeepLinkDialog).toHaveBeenCalledWith(false); + expect(hideModal).toHaveBeenCalledTimes(1); + }); + + it('should match snapshot', () => { + const { container } = renderWithProvider(, store); + + expect(container).toMatchSnapshot(); + }); + + it('shows custodian name when iconUrl is undefined', () => { + const customMockStore = { + ...mockStore, + metamask: { + ...testData.metamask, + ...mockStore.metamask, + mmiConfiguration: { + custodians: [ + { + refreshTokenUrl: + 'https://saturn-custody.dev.metamask-institutional.io/oauth/token', + name: 'saturn-dev', + displayName: 'Saturn Custody', + enabled: true, + mmiApiUrl: 'https://api.dev.metamask-institutional.io/v1', + websocketApiUrl: + 'wss://websocket.dev.metamask-institutional.io/v1/ws', + apiBaseUrl: + 'https://saturn-custody.dev.metamask-institutional.io/eth', + iconUrl: null, + isNoteToTraderSupported: true, + }, + ], + }, + }, + }; + + store = configureStore()(customMockStore); + + const { getByText } = renderWithProvider(, store); + + expect(getByText(mockedCustodianName)).toBeVisible(); + }); + + it('shows text that comes from modal state if defined', () => { + const mockModalStateText = 'test modal state text'; + const customMockStore = { + ...mockStore, + appState: { + ...testData.appState, + modal: { + modalState: { + props: { + link: { + url: 'test-url', + ethereum: { + accounts: [{}], + }, + text: mockModalStateText, + action: '', + }, + }, + }, + }, + }, + }; + + store = configureStore()(customMockStore); + + const { getByText } = renderWithProvider(, store); + + expect(getByText(mockModalStateText)).toBeVisible(); + }); + + it('shows action text that comes from modal state if defined', () => { + const mockModalStateActionText = 'test modal state action text'; + const customMockStore = { + ...mockStore, + appState: { + ...testData.appState, + modal: { + modalState: { + props: { + link: { + url: 'test-url', + ethereum: { + accounts: [{}], + }, + text: '', + action: mockModalStateActionText, + }, + }, + }, + }, + }, + }; + + store = configureStore()(customMockStore); + + const { getByText } = renderWithProvider(, store); + + expect(getByText(mockModalStateActionText)).toBeVisible(); + }); +}); diff --git a/ui/components/institutional/custody-confirm-link-modal/index.js b/ui/components/institutional/custody-confirm-link-modal/index.js new file mode 100644 index 000000000..da3cf4bc2 --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/index.js @@ -0,0 +1,3 @@ +import CustodyConfirmLink from './custody-confirm-link-modal'; + +export default CustodyConfirmLink; diff --git a/ui/components/institutional/custody-confirm-link-modal/index.scss b/ui/components/institutional/custody-confirm-link-modal/index.scss new file mode 100644 index 000000000..f9771d761 --- /dev/null +++ b/ui/components/institutional/custody-confirm-link-modal/index.scss @@ -0,0 +1,18 @@ +.custody-confirm-link { + &__description { + border-bottom: 1px solid var(--brand-colors-grey-grey200); + } + + &__img { + margin: 0 20px; + display: block; + padding: 20px 0; + width: 45px; + text-align: center; + } + + &__btn { + width: 300px !important; + margin: 20px auto; + } +} diff --git a/ui/components/institutional/institutional-components.scss b/ui/components/institutional/institutional-components.scss new file mode 100644 index 000000000..8ae612682 --- /dev/null +++ b/ui/components/institutional/institutional-components.scss @@ -0,0 +1,11 @@ +/** +* Please import your styles in order of atomicity. +* The most atomic styles should be imported first. +* This will help improve specificity and reduce the chance of +* unintended overrides. +**/ +@import 'compliance-details/index'; +@import 'compliance-settings/index'; +@import 'jwt-dropdown/jwt-dropdown'; +@import 'jwt-url-form/jwt-url-form'; +@import 'note-to-trader/index'; diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js index 0f40723d4..d5cb84547 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.js @@ -15,8 +15,8 @@ import { FLEX_WRAP, FLEX_DIRECTION, BorderRadius, - FONT_WEIGHT, - TEXT_ALIGN, + FontWeight, + TextAlign, AlignItems, } from '../../../helpers/constants/design-system'; @@ -53,7 +53,7 @@ const InteractiveReplacementTokenModal = () => { alignItems={AlignItems.center} paddingTop={5} > - + { ); } else { img = ( - + {custodian.displayName} ); @@ -76,8 +76,8 @@ const InteractiveReplacementTokenModal = () => { {t('custodyRefreshTokenModalTitle')} @@ -85,18 +85,18 @@ const InteractiveReplacementTokenModal = () => { as="p" paddingTop={4} paddingBottom={6} - textAlign={TEXT_ALIGN.LEFT} + textAlign={TextAlign.Left} > {t('custodyRefreshTokenModalDescription', [custodian.displayName])} - + {t('custodyRefreshTokenModalSubtitle')} {t('custodyRefreshTokenModalDescription1')} @@ -105,7 +105,7 @@ const InteractiveReplacementTokenModal = () => { marginTop={4} paddingTop={4} paddingBottom={6} - textAlign={TEXT_ALIGN.LEFT} + textAlign={TextAlign.Left} > {t('custodyRefreshTokenModalDescription2')} diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.stories.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.stories.js index 86c03504c..9ef1baac8 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.stories.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.stories.js @@ -42,7 +42,7 @@ const customData = { custodianName: 'saturn-dev', }, }, - provider: { + providerConfig: { type: 'test', }, selectedAddress: '0xAddress', diff --git a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js index 4a78a2237..c6a1f8545 100644 --- a/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js +++ b/ui/components/institutional/interactive-replacement-token-modal/interactive-replacement-token-modal.test.js @@ -45,7 +45,7 @@ describe('Interactive Replacement Token Modal', function () { custodianName: 'saturn-dev', }, }, - provider: { + providerConfig: { type: 'test', }, selectedAddress: '0xAddress', diff --git a/ui/components/institutional/interactive-replacement-token-notification/index.js b/ui/components/institutional/interactive-replacement-token-notification/index.js new file mode 100644 index 000000000..e92242cea --- /dev/null +++ b/ui/components/institutional/interactive-replacement-token-notification/index.js @@ -0,0 +1 @@ +export { default } from './interactive-replacement-token-notification'; diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js new file mode 100644 index 000000000..80c8bd93f --- /dev/null +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.js @@ -0,0 +1,143 @@ +import React, { useState, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { getCurrentKeyring, getSelectedAddress } from '../../../selectors'; +import { getInteractiveReplacementToken } from '../../../selectors/institutional/selectors'; +import { getIsUnlocked } from '../../../ducks/metamask/metamask'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { mmiActionsFactory } from '../../../store/institutional/institution-background'; +import { sha256 } from '../../../../shared/modules/hash.utils'; +import { + Size, + IconColor, + AlignItems, + DISPLAY, + BLOCK_SIZES, + JustifyContent, + TextColor, + TextVariant, + BackgroundColor, +} from '../../../helpers/constants/design-system'; +import { + Icon, + IconName, + IconSize, + ButtonLink, + Text, +} from '../../component-library'; + +import Box from '../../ui/box'; + +const InteractiveReplacementTokenNotification = ({ isVisible }) => { + const t = useI18nContext(); + const dispatch = useDispatch(); + const mmiActions = mmiActionsFactory(); + + const keyring = useSelector(getCurrentKeyring); + const address = useSelector(getSelectedAddress); + const isUnlocked = useSelector(getIsUnlocked); + const interactiveReplacementToken = useSelector( + getInteractiveReplacementToken, + ); + + const [showNotification, setShowNotification] = useState(isVisible); + + useEffect(() => { + const handleShowNotification = async () => { + const hasInteractiveReplacementToken = + interactiveReplacementToken && + Boolean(Object.keys(interactiveReplacementToken).length); + + if (!/^Custody/u.test(keyring.type)) { + setShowNotification(false); + return; + } else if (!hasInteractiveReplacementToken) { + setShowNotification(false); + return; + } + + const token = await dispatch(mmiActions.getCustodianToken()); + const custodyAccountDetails = await dispatch( + mmiActions.getAllCustodianAccountsWithToken( + keyring.type.split(' - ')[1], + token, + ), + ); + + const showNotificationValue = + isUnlocked && + interactiveReplacementToken.oldRefreshToken && + custodyAccountDetails && + Boolean(Object.keys(custodyAccountDetails).length); + + let tokenAccount; + + if (Array.isArray(custodyAccountDetails)) { + tokenAccount = custodyAccountDetails + .filter( + (item) => item.address.toLowerCase() === address.toLowerCase(), + ) + .map((item) => ({ + token: item.authDetails?.refreshToken, + }))[0]; + } + + const refreshTokenAccount = await sha256( + tokenAccount?.token + interactiveReplacementToken.url, + ); + + setShowNotification( + showNotificationValue && + refreshTokenAccount === interactiveReplacementToken.oldRefreshToken, + ); + }; + + handleShowNotification(); + }, [ + dispatch, + address, + interactiveReplacementToken, + isUnlocked, + keyring, + mmiActions, + ]); + + return showNotification ? ( + + + + {t('custodySessionExpired')} + + { + dispatch(mmiActions.showInteractiveReplacementTokenModal()); + }} + > + {t('learnMore')} + + + ) : null; +}; + +export default InteractiveReplacementTokenNotification; + +InteractiveReplacementTokenNotification.propTypes = { + isVisible: PropTypes.bool, +}; diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.scss b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.scss new file mode 100644 index 000000000..06aba2f4b --- /dev/null +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.scss @@ -0,0 +1,15 @@ +.interactive-replacement-token-notification { + height: 24px; + + @media screen and (min-width: $break-large) { + width: 85vw; + } + + @media screen and (min-width: 768px) { + width: 80vw; + } + + @media screen and (min-width: 1280px) { + width: 62vw; + } +} diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.stories.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.stories.js new file mode 100644 index 000000000..33e750a8c --- /dev/null +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.stories.js @@ -0,0 +1,59 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import InteractiveReplacementTokenNotification from '.'; + +const customData = { + ...testData, + metamask: { + ...testData.metamask, + providerConfig: { + type: 'test', + }, + selectedAddress: '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', + identities: { + '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281': { + address: '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', + name: 'Custodian A', + }, + }, + isUnlocked: true, + interactiveReplacementToken: { + oldRefreshToken: + '81f96a88b6cbc5f50d3864122349fa9a9755833ee82a7e3cf6f268c78aab51ab', + url: 'url', + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + keyrings: [ + { + type: 'Custody - Saturn', + accounts: ['0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281'], + }, + ], + }, +}; + +const store = configureStore(customData); + +export default { + title: 'Components/Institutional/InteractiveReplacementToken-Notification', + decorators: [(story) => {story()}], + component: InteractiveReplacementTokenNotification, + args: { + isVisible: true, + }, + argTypes: { + onClick: { + action: 'onClick', + }, + }, +}; + +export const DefaultStory = (args) => ( + +); + +DefaultStory.storyName = 'InteractiveReplacementTokenNotification'; diff --git a/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js new file mode 100644 index 000000000..817600e2d --- /dev/null +++ b/ui/components/institutional/interactive-replacement-token-notification/interactive-replacement-token-notification.test.js @@ -0,0 +1,156 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { screen, fireEvent } from '@testing-library/react'; +import { act } from 'react-dom/test-utils'; +import { sha256 } from '../../../../shared/modules/hash.utils'; +import { KeyringType } from '../../../../shared/constants/keyring'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import InteractiveReplacementTokenNotification from './interactive-replacement-token-notification'; + +jest.mock('../../../../shared/modules/hash.utils'); + +const mockedShowInteractiveReplacementTokenModal = jest + .fn() + .mockReturnValue({ type: 'TYPE' }); + +const mockedGetCustodianToken = jest + .fn() + .mockReturnValue({ type: 'Custody', payload: 'token' }); + +const mockedGetAllCustodianAccountsWithToken = jest.fn().mockReturnValue({ + type: 'TYPE', + payload: [ + { + address: '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', + authDetails: { refreshToken: 'def' }, + }, + ], +}); + +jest.mock('../../../store/institutional/institution-background', () => ({ + mmiActionsFactory: () => ({ + getCustodianToken: mockedGetCustodianToken, + getAllCustodianAccountsWithToken: mockedGetAllCustodianAccountsWithToken, + showInteractiveReplacementTokenModal: + mockedShowInteractiveReplacementTokenModal, + }), +})); + +describe('Interactive Replacement Token Notification', () => { + const selectedAddress = '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281'; + + const identities = { + '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281': { + address: '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', + name: 'Custodian A', + }, + }; + + const mockStore = { + metamask: { + providerConfig: { + type: 'test', + }, + selectedAddress, + identities, + isUnlocked: false, + interactiveReplacementToken: { oldRefreshToken: 'abc' }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + keyrings: [ + { + type: KeyringType.imported, + accounts: ['0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', '0x2'], + }, + { + type: KeyringType.ledger, + accounts: [], + }, + ], + }, + }; + + it('should not render if show notification is false', () => { + const store = configureMockStore([thunk])(mockStore); + + renderWithProvider(, store); + + expect( + screen.queryByTestId('interactive-replacement-token-notification'), + ).not.toBeInTheDocument(); + }); + + it('should render if show notification is true and click on learn more', async () => { + const customMockStore = { + ...mockStore, + metamask: { + ...mockStore.metamask, + isUnlocked: true, + interactiveReplacementToken: { oldRefreshToken: 'def', url: 'url' }, + keyrings: [ + { + type: 'Custody - Saturn', + accounts: ['0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281'], + }, + ], + }, + }; + const store = configureMockStore([thunk])(customMockStore); + + sha256.mockReturnValue('def'); + await act(async () => { + renderWithProvider(, store); + }); + + expect( + screen.getByTestId('interactive-replacement-token-notification'), + ).toBeInTheDocument(); + expect(screen.getByTestId('show-modal')).toBeInTheDocument(); + + await act(async () => { + fireEvent.click(screen.getByTestId('show-modal')); + }); + + expect(mockedShowInteractiveReplacementTokenModal).toHaveBeenCalled(); + }); + + it('should render and call showNotification when component starts', async () => { + const customMockStore = { + ...mockStore, + metamask: { + ...mockStore.metamask, + isUnlocked: true, + interactiveReplacementToken: { oldRefreshToken: 'def', url: 'url' }, + keyrings: [ + { + type: 'Custody - Saturn', + accounts: ['0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281', '0x2'], + }, + { + type: KeyringType.ledger, + accounts: [], + }, + ], + }, + }; + + const store = configureMockStore([thunk])(customMockStore); + + sha256.mockReturnValue('def'); + await act(async () => { + renderWithProvider(, store); + }); + + expect(mockedGetCustodianToken).toHaveBeenCalled(); + + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, 0)); + }); + + expect( + screen.getByTestId('interactive-replacement-token-notification'), + ).toBeInTheDocument(); + }); +}); diff --git a/ui/components/institutional/jwt-url-form/__snapshots__/jwt-url-form.test.js.snap b/ui/components/institutional/jwt-url-form/__snapshots__/jwt-url-form.test.js.snap index cdf419d89..c84e7439d 100644 --- a/ui/components/institutional/jwt-url-form/__snapshots__/jwt-url-form.test.js.snap +++ b/ui/components/institutional/jwt-url-form/__snapshots__/jwt-url-form.test.js.snap @@ -17,7 +17,6 @@ exports[`JwtUrlForm shows JWT text area when no jwt token exists 1`] = ` input text

+ + +
+

+ API URL +

+
+ +
+
+ +
+ + +
+ + + +`; + +exports[`CustodyPage renders CustodyPage 3`] = `
`; diff --git a/ui/pages/institutional/custody/custody.js b/ui/pages/institutional/custody/custody.js new file mode 100644 index 000000000..828eb3020 --- /dev/null +++ b/ui/pages/institutional/custody/custody.js @@ -0,0 +1,589 @@ +import React, { + useState, + useMemo, + useCallback, + useEffect, + useContext, +} from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { v4 as uuidv4 } from 'uuid'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { mmiActionsFactory } from '../../../store/institutional/institution-background'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + ButtonIcon, + Button, + Text, + Label, + IconName, + IconSize, + BUTTON_SIZES, + BUTTON_VARIANT, +} from '../../../components/component-library'; +import { + AlignItems, + DISPLAY, + FLEX_DIRECTION, + FONT_WEIGHT, + Color, + JustifyContent, + BorderRadius, + BorderColor, + BLOCK_SIZES, + TextColor, + TEXT_ALIGN, + TextVariant, +} from '../../../helpers/constants/design-system'; +import Box from '../../../components/ui/box'; +import { + CUSTODY_ACCOUNT_DONE_ROUTE, + DEFAULT_ROUTE, +} from '../../../helpers/constants/routes'; +import { getCurrentChainId } from '../../../selectors'; +import { getMMIConfiguration } from '../../../selectors/institutional/selectors'; +import CustodyAccountList from '../connect-custody/account-list'; +import JwtUrlForm from '../../../components/institutional/jwt-url-form'; + +const CustodyPage = () => { + const t = useI18nContext(); + const history = useHistory(); + const trackEvent = useContext(MetaMetricsContext); + const dispatch = useDispatch(); + + const mmiActions = mmiActionsFactory(); + const currentChainId = useSelector(getCurrentChainId); + const { custodians } = useSelector(getMMIConfiguration); + + const [selectedAccounts, setSelectedAccounts] = useState({}); + const [selectedCustodianName, setSelectedCustodianName] = useState(''); + const [selectedCustodianImage, setSelectedCustodianImage] = useState(null); + const [selectedCustodianDisplayName, setSelectedCustodianDisplayName] = + useState(''); + const [selectedCustodianType, setSelectedCustodianType] = useState(''); + const [connectError, setConnectError] = useState(''); + const [currentJwt, setCurrentJwt] = useState(''); + const [selectError, setSelectError] = useState(''); + const [jwtList, setJwtList] = useState([]); + const [apiUrl, setApiUrl] = useState(''); + const [addNewTokenClicked, setAddNewTokenClicked] = useState(false); + const [chainId, setChainId] = useState(0); + const [connectRequest, setConnectRequest] = useState(undefined); + const [accounts, setAccounts] = useState(); + + const custodianButtons = useMemo(() => { + const custodianItems = []; + custodians.forEach((custodian) => { + if ( + (!custodian.production && + process.env.METAMASK_ENVIRONMENT === 'production') || + custodian.hidden || + (connectRequest && + Object.keys(connectRequest).length && + custodian.name !== selectedCustodianName) + ) { + return; + } + + custodianItems.push( + + + {custodian.iconUrl && ( + {custodian.displayName} + )} + {custodian.displayName} + + + + , + ); + }); + + return custodianItems; + }, [connectRequest, custodians, dispatch, selectedCustodianName]); + + const handleConnectError = useCallback( + (e) => { + let errorMessage; + const detailedError = e.message.split(':'); + + if (detailedError.length > 1 && !isNaN(parseInt(detailedError[0], 10))) { + if (parseInt(detailedError[0], 10) === 401) { + // Authentication Error + errorMessage = + 'Authentication error. Please ensure you have entered the correct token'; + } + } + + if (/Network Error/u.test(e.message)) { + errorMessage = + 'Network error. Please ensure you have entered the correct API URL'; + } + + if (!errorMessage) { + errorMessage = e.message; + } + + setConnectError( + `Something went wrong connecting your custodian account. Error details: ${errorMessage}`, + ); + trackEvent({ + category: 'MMI', + event: 'Connect to custodian error', + properties: { + custodian: selectedCustodianName, + }, + }); + }, + [selectedCustodianName, trackEvent], + ); + + const getCustodianAccounts = useCallback( + async (token, custody, getNonImportedAccounts) => { + return await dispatch( + mmiActions.getCustodianAccounts( + token, + apiUrl, + custody || selectedCustodianType, + getNonImportedAccounts, + ), + ); + }, + [dispatch, mmiActions, apiUrl, selectedCustodianType], + ); + + const connect = useCallback(async () => { + try { + // If you have one JWT already, but no dropdown yet, currentJwt is null! + const jwt = currentJwt || jwtList[0]; + setConnectError(''); + const accountsValue = await getCustodianAccounts( + jwt, + apiUrl, + selectedCustodianType, + true, + ); + setAccounts(accountsValue); + trackEvent({ + category: 'MMI', + event: 'Connect to custodian', + properties: { + custodian: selectedCustodianName, + apiUrl, + rpc: Boolean(connectRequest), + }, + }); + } catch (e) { + handleConnectError(e); + } + }, [ + apiUrl, + connectRequest, + currentJwt, + getCustodianAccounts, + handleConnectError, + jwtList, + selectedCustodianName, + selectedCustodianType, + trackEvent, + ]); + + useEffect(() => { + const fetchConnectRequest = async () => { + const connectRequestValue = await dispatch( + mmiActions.getCustodianConnectRequest(), + ); + setChainId(parseInt(currentChainId, 16)); + + // check if it's empty object + if (Object.keys(connectRequestValue).length) { + setConnectRequest(connectRequestValue); + setCurrentJwt( + connectRequestValue.token || + (await dispatch(mmiActions.getCustodianToken())), + ); + setSelectedCustodianType(connectRequestValue.custodianType); + setSelectedCustodianName(connectRequestValue.custodianName); + setApiUrl(connectRequestValue.apiUrl); + connect(); + } + }; + + // call the function + fetchConnectRequest() + // make sure to catch any error + .catch(console.error); + }, [dispatch, connect, currentChainId, mmiActions]); + + useEffect(() => { + const handleNetworkChange = async () => { + if (!isNaN(chainId)) { + const jwt = currentJwt || jwtList[0]; + + if (jwt && jwt.length) { + setAccounts( + await getCustodianAccounts( + jwt, + apiUrl, + selectedCustodianType, + true, + ), + ); + } + } + }; + + if (parseInt(chainId, 16) !== chainId) { + setChainId(parseInt(currentChainId, 16)); + handleNetworkChange(); + } + }, [ + getCustodianAccounts, + apiUrl, + currentJwt, + jwtList, + selectedCustodianType, + currentChainId, + chainId, + ]); + + const cancelConnectCustodianToken = () => { + setSelectedCustodianName(''); + setSelectedCustodianType(''); + setSelectedCustodianImage(null); + setSelectedCustodianDisplayName(''); + setApiUrl(''); + setCurrentJwt(''); + setConnectError(''); + setSelectError(''); + }; + + const setSelectAllAccounts = (e) => { + const allAccounts = {}; + + if (e.currentTarget.checked) { + accounts.forEach((account) => { + allAccounts[account.address] = { + name: account.name, + custodianDetails: account.custodianDetails, + labels: account.labels, + token: currentJwt, + apiUrl, + chainId: account.chainId, + custodyType: selectedCustodianType, + custodyName: selectedCustodianName, + }; + }); + setSelectedAccounts(allAccounts); + } else { + setSelectedAccounts({}); + } + }; + + return ( + + {connectError && ( + + {connectError} + + )} + + {selectError && ( + + {selectError} + + )} + + {!accounts && !selectedCustodianType ? ( + + history.push(DEFAULT_ROUTE)} + display={DISPLAY.FLEX} + /> + + {t('connectCustodialAccountTitle')} + + + {t('connectCustodialAccountMsg')} + + +
    {custodianButtons}
+
+
+ ) : null} + + {!accounts && selectedCustodianType && ( + <> + + cancelConnectCustodianToken()} + display={[DISPLAY.FLEX]} + /> + + + {selectedCustodianImage && ( + {selectedCustodianDisplayName} + )} + {selectedCustodianDisplayName} + + + + {t('enterCustodianToken', [selectedCustodianDisplayName])} + + + + setCurrentJwt(jwt)} + jwtInputText={t('pasteJWTToken')} + apiUrl={apiUrl} + urlInputText={t('custodyApiUrl', [selectedCustodianDisplayName])} + onUrlChange={(url) => setApiUrl(url)} + /> + + + + + + + )} + + {accounts && accounts.length > 0 && ( + <> + + {t('selectAnAccount')} + + {t('selectAnAccountHelp')} + + + + setSelectAllAccounts(e)} + checked={Object.keys(selectedAccounts).length === accounts.length} + /> + + + { + if (selectedAccounts[account.address]) { + delete selectedAccounts[account.address]; + } else { + selectedAccounts[account.address] = { + name: account.name, + custodianDetails: account.custodianDetails, + labels: account.labels, + token: currentJwt, + apiUrl, + chainId: account.chainId, + custodyType: selectedCustodianType, + custodyName: selectedCustodianName, + }; + } + + setSelectedAccounts(selectedAccounts); + }} + selectedAccounts={selectedAccounts} + onAddAccounts={async () => { + try { + await dispatch( + mmiActions.connectCustodyAddresses( + selectedCustodianType, + selectedCustodianName, + selectedAccounts, + ), + ); + const selectedCustodian = custodians.find( + (custodian) => custodian.name === selectedCustodianName, + ); + history.push({ + pathname: CUSTODY_ACCOUNT_DONE_ROUTE, + state: { + imgSrc: selectedCustodian.iconUrl, + title: t('custodianAccountAddedTitle'), + description: t('custodianAccountAddedDesc'), + }, + }); + trackEvent({ + category: 'MMI', + event: 'Custodial accounts connected', + properties: { + custodian: selectedCustodianName, + numberOfAccounts: Object.keys(selectedAccounts).length, + chainId, + }, + }); + } catch (e) { + setSelectError(e.message); + } + }} + onCancel={() => { + setAccounts(null); + setSelectedCustodianName(null); + setSelectedCustodianType(null); + setSelectedAccounts({}); + setCurrentJwt(''); + setApiUrl(''); + setAddNewTokenClicked(false); + + if (Object.keys(connectRequest).length) { + history.push(DEFAULT_ROUTE); + } + + trackEvent({ + category: 'MMI', + event: 'Connect to custodian cancel', + properties: { + custodian: selectedCustodianName, + numberOfAccounts: Object.keys(selectedAccounts).length, + chainId, + }, + }); + }} + /> + + )} + + {accounts && accounts.length === 0 && ( + + + {t('allCustodianAccountsConnectedTitle')} + + + {t('allCustodianAccountsConnectedSubtitle')} + + + + + + + )} +
+ ); +}; + +export default CustodyPage; diff --git a/ui/pages/institutional/custody/custody.stories.js b/ui/pages/institutional/custody/custody.stories.js new file mode 100644 index 000000000..1b34abc27 --- /dev/null +++ b/ui/pages/institutional/custody/custody.stories.js @@ -0,0 +1,52 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import CustodyPage from '.'; + +const customData = { + ...testData, + metamask: { + ...testData.metamask, + mmiConfiguration: { + portfolio: { + enabled: true, + url: 'https://portfolio.io', + }, + custodians: [ + { + type: 'Saturn', + name: 'saturn', + apiUrl: 'https://saturn-custody.dev.metamask-institutional.io', + iconUrl: + 'https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg', + displayName: 'Saturn Custody', + production: true, + refreshTokenUrl: null, + isNoteToTraderSupported: false, + version: 1, + }, + ], + }, + }, +}; + +const store = configureStore(customData); + +export default { + title: 'Pages/Institutional/CustodyPage', + decorators: [(story) => {story()}], + component: CustodyPage, + argTypes: { + onClick: { + action: 'onClick', + }, + onChange: { + action: 'onChange', + }, + }, +}; + +export const DefaultStory = (args) => ; + +DefaultStory.storyName = 'CustodyPage'; diff --git a/ui/pages/institutional/custody/custody.test.js b/ui/pages/institutional/custody/custody.test.js new file mode 100644 index 000000000..f944d33aa --- /dev/null +++ b/ui/pages/institutional/custody/custody.test.js @@ -0,0 +1,113 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; +import { fireEvent, waitFor, screen } from '@testing-library/react'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import CustodyPage from '.'; + +const mockedReturnedValue = jest.fn().mockReturnValue({ type: 'TYPE' }); +const mockedGetCustodianJWTList = jest.fn().mockReturnValue({ type: 'TYPE' }); + +const mockedGetCustodianAccounts = jest.fn().mockReturnValue(async () => null); +const mockedGetCustodianToken = jest.fn().mockReturnValue('testJWT'); + +const mockedGetCustodianConnectRequest = jest.fn().mockReturnValue({ + type: 'TYPE', + custodian: 'saturn', + token: 'token', + apiUrl: 'url', + custodianType: 'JSON-RPC', + custodianName: 'Saturn', +}); + +jest.mock('../../../store/institutional/institution-background', () => ({ + mmiActionsFactory: () => ({ + getCustodianConnectRequest: mockedGetCustodianConnectRequest, + getCustodianToken: mockedGetCustodianToken, + getCustodianAccounts: mockedGetCustodianAccounts, + getCustodianAccountsByAddress: mockedReturnedValue, + getCustodianJWTList: mockedGetCustodianJWTList, + connectCustodyAddresses: mockedReturnedValue, + }), +})); + +describe('CustodyPage', function () { + const mockStore = { + metamask: { + providerConfig: { chainId: 0x1, type: 'test' }, + mmiConfiguration: { + portfolio: { + enabled: true, + url: 'https://portfolio.io', + }, + custodians: [ + { + type: 'Saturn', + name: 'saturn', + apiUrl: 'https://saturn-custody.dev.metamask-institutional.io', + iconUrl: + 'https://saturn-custody-ui.dev.metamask-institutional.io/saturn.svg', + displayName: 'Saturn Custody', + production: true, + refreshTokenUrl: null, + isNoteToTraderSupported: false, + version: 1, + }, + ], + }, + preferences: { + useNativeCurrencyAsPrimaryCurrency: true, + }, + appState: { + isLoading: false, + }, + history: { + mostRecentOverviewPage: '/', + }, + }, + }; + + const store = configureMockStore([thunk])(mockStore); + + it('renders CustodyPage', async () => { + const { container } = renderWithProvider(, store); + + await waitFor(() => { + expect(container).toMatchSnapshot(); + }); + }); + + it('opens connect custody without any custody selected', async () => { + const { getByTestId } = renderWithProvider(, store); + + await waitFor(() => { + expect(getByTestId('custody-connect-button')).toBeDefined(); + }); + }); + + it('calls getCustodianJwtList on custody select when connect btn is click', async () => { + const { getByTestId } = renderWithProvider(, store); + + const custodyBtn = getByTestId('custody-connect-button'); + await waitFor(() => { + fireEvent.click(custodyBtn); + }); + + await waitFor(() => { + expect(mockedGetCustodianJWTList).toHaveBeenCalled(); + }); + }); + + it('clicks connect button and shows the jwt form', async () => { + const { getByTestId } = renderWithProvider(, store); + const custodyBtn = getByTestId('custody-connect-button'); + + await waitFor(() => { + fireEvent.click(custodyBtn); + }); + + await waitFor(() => { + expect(screen.getByTestId('jwt-form-connect-button')).toBeInTheDocument(); + }); + }); +}); diff --git a/ui/pages/institutional/custody/index.js b/ui/pages/institutional/custody/index.js new file mode 100644 index 000000000..a53ef30e0 --- /dev/null +++ b/ui/pages/institutional/custody/index.js @@ -0,0 +1 @@ +export { default } from './custody'; diff --git a/ui/pages/institutional/custody/index.scss b/ui/pages/institutional/custody/index.scss new file mode 100644 index 000000000..d2f7ef0fa --- /dev/null +++ b/ui/pages/institutional/custody/index.scss @@ -0,0 +1,14 @@ +@import '../../../components/institutional/jwt-dropdown/jwt-dropdown.scss'; +@import '../../../components/institutional/jwt-url-form/jwt-url-form.scss'; + +.custody-accounts-empty { + min-height: 300px; + + &__footer { + border-top: 1px solid var(--color-border-muted); + position: absolute; + width: 100%; + bottom: 0; + left: 0; + } +} diff --git a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.test.js b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.test.js index 0b9d77dd6..47eb95d9e 100644 --- a/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.test.js +++ b/ui/pages/institutional/institutional-entity-done-page/institutional-entity-done-page.test.js @@ -19,7 +19,7 @@ const render = () => { const store = configureStore({ ...mockState, metamask: { - provider: { + providerConfig: { type: 'test', }, }, diff --git a/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap b/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap new file mode 100644 index 000000000..9d57ea9b9 --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/__snapshots__/interactive-replacement-token-page.test.js.snap @@ -0,0 +1,119 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Interactive Replacement Token Page should reject if there are errors 1`] = ` +
+
+
+
+ Replace custodian token + + +
+
+ This is will replace the custodian token for the following address: +
+
+
+
+
+
+
+ +
+
+`; + +exports[`Interactive Replacement Token Page should reject if there are errors 2`] = ` +
+
+
+
+ Replace custodian token + + failed +
+
+
+
+

+ Please go to displayName and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again. +

+
+
+
+ +
+
+`; diff --git a/ui/pages/institutional/interactive-replacement-token-page/index.js b/ui/pages/institutional/interactive-replacement-token-page/index.js new file mode 100644 index 000000000..0d0241f73 --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/index.js @@ -0,0 +1,3 @@ +import InteractiveReplacementTokenPage from './interactive-replacement-token-page'; + +export default InteractiveReplacementTokenPage; diff --git a/ui/pages/institutional/interactive-replacement-token-page/index.scss b/ui/pages/institutional/interactive-replacement-token-page/index.scss new file mode 100644 index 000000000..a1d39a9c9 --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/index.scss @@ -0,0 +1,23 @@ +.interactive-replacement-token-page { + opacity: 0.8; + + &__item { + border-bottom: 1px solid --color-border-default; + + &-clipboard { + background-color: transparent; + } + } + + &__item:first-child { + margin-top: 12px; + } + + &__item:last-child { + border: 0; + } + + &__item:hover { + background-color: rgba(0, 0, 0, 0.03); + } +} diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js new file mode 100644 index 000000000..751168841 --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.js @@ -0,0 +1,349 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import PropTypes from 'prop-types'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; +import { getMostRecentOverviewPage } from '../../../ducks/history/history'; +import { getMetaMaskAccounts } from '../../../selectors'; +import Button from '../../../components/ui/button'; +import CustodyLabels from '../../../components/institutional/custody-labels/custody-labels'; +import PulseLoader from '../../../components/ui/pulse-loader'; +import { INSTITUTIONAL_FEATURES_DONE_ROUTE } from '../../../helpers/constants/routes'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; +import { CHAIN_IDS } from '../../../../shared/constants/network'; +import { shortenAddress } from '../../../helpers/utils/util'; +import Tooltip from '../../../components/ui/tooltip'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { + mmiActionsFactory, + showInteractiveReplacementTokenBanner, +} from '../../../store/institutional/institution-background'; +import Box from '../../../components/ui/box'; +import { + Text, + Label, + Icon, + ButtonLink, + IconName, + IconSize, +} from '../../../components/component-library'; +import { + OVERFLOW_WRAP, + TextColor, + JustifyContent, + BLOCK_SIZES, + DISPLAY, + FLEX_DIRECTION, + IconColor, +} from '../../../helpers/constants/design-system'; +import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'; + +const getButtonLinkHref = ({ address }) => { + const url = SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET]; + return `${url}address/${address}`; +}; + +export default function InteractiveReplacementTokenPage({ history }) { + const dispatch = useDispatch(); + const isMountedRef = useRef(false); + const mmiActions = mmiActionsFactory(); + const { address } = useSelector((state) => state.metamask.modal.props); + const { + selectedAddress, + custodyAccountDetails, + interactiveReplacementToken, + mmiConfiguration, + } = useSelector((state) => state.metamask); + const { custodianName } = + custodyAccountDetails[toChecksumHexAddress(address || selectedAddress)] || + {}; + const { url } = interactiveReplacementToken || {}; + const { custodians } = mmiConfiguration; + const custodian = + custodians.find((item) => item.name === custodianName) || {}; + const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage); + const metaMaskAccounts = useSelector(getMetaMaskAccounts); + const connectRequests = useSelector( + (state) => state.metamask.institutionalFeatures?.connectRequests, + ); + const [isLoading, setIsLoading] = useState(false); + const [tokenAccounts, setTokenAccounts] = useState([]); + const [error, setError] = useState(false); + const t = useI18nContext(); + const [copied, handleCopy] = useCopyToClipboard(); + const { + removeAddTokenConnectRequest, + setCustodianNewRefreshToken, + getCustodianAccounts, + } = mmiActions; + const connectRequest = connectRequests ? connectRequests[0] : undefined; + + useEffect(() => { + isMountedRef.current = true; + return () => (isMountedRef.current = false); + }, []); + + useEffect(() => { + const getTokenAccounts = async () => { + if (!connectRequest) { + history.push(mostRecentOverviewPage); + return; + } + + try { + const custodianAccounts = await dispatch( + getCustodianAccounts( + connectRequest.token, + connectRequest.apiUrl, + connectRequest.service, + false, + ), + ); + + const filteredAccounts = custodianAccounts.filter( + (account) => metaMaskAccounts[account.address.toLowerCase()], + ); + + const mappedAccounts = filteredAccounts.map((account) => ({ + address: account.address, + name: account.name, + labels: account.labels, + balance: + metaMaskAccounts[account.address.toLowerCase()]?.balance || 0, + })); + + if (isMountedRef.current) { + setTokenAccounts(mappedAccounts); + setIsLoading(false); + } + } catch (e) { + setError(true); + setIsLoading(false); + } + }; + + getTokenAccounts(); + // We just want to get the accounts in the render of the component + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + if (!connectRequest) { + history.push(mostRecentOverviewPage); + return null; + } + + const onRemoveAddTokenConnectRequest = ({ origin, apiUrl, token }) => { + dispatch( + removeAddTokenConnectRequest({ + origin, + apiUrl, + token, + }), + ); + }; + + const handleReject = () => { + onRemoveAddTokenConnectRequest(connectRequest); + history.push(mostRecentOverviewPage); + }; + + const handleApprove = async () => { + if (error) { + global.platform.openTab({ + url, + }); + handleReject(); + return; + } + + setIsLoading(true); + + try { + await Promise.all( + tokenAccounts.map(async (account) => { + await dispatch( + setCustodianNewRefreshToken({ + address: account.address, + newAuthDetails: { + refreshToken: connectRequest.token, + refreshTokenUrl: connectRequest.apiUrl, + }, + }), + ); + }), + ); + + dispatch(showInteractiveReplacementTokenBanner({})); + + onRemoveAddTokenConnectRequest(connectRequest); + + history.push({ + pathname: INSTITUTIONAL_FEATURES_DONE_ROUTE, + state: { + imgSrc: custodian?.iconUrl, + title: t('custodianReplaceRefreshTokenChangedTitle'), + description: t('custodianReplaceRefreshTokenChangedSubtitle'), + }, + }); + + if (isMountedRef.current) { + setIsLoading(false); + } + } catch (e) { + console.error(e); + } + }; + + return ( + + + + {t('custodianReplaceRefreshTokenTitle')}{' '} + {error ? t('failed').toLowerCase() : ''} + + {!error && ( + + {t('custodianReplaceRefreshTokenSubtitle')} + + )} + + + + {error ? ( + + {t('custodianReplaceRefreshTokenChangedFailed', [ + custodian.displayName || 'Custodian', + ])} + + ) : null} + + {tokenAccounts.map((account, idx) => { + return ( + + + + + + {account.labels && ( + + )} + + + + ); + })} + + + + + {isLoading ? ( +
+ +
+ ) : ( +
+ + +
+ )} +
+
+ ); +} + +InteractiveReplacementTokenPage.propTypes = { + history: PropTypes.object, +}; diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.stories.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.stories.js new file mode 100644 index 000000000..ed51dbc78 --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.stories.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { action } from '@storybook/addon-actions'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import InteractiveReplacementTokenPage from '.'; + +const address = '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F'; +const customData = { + ...testData, + metamask: { + ...testData.metamask, + modal: { props: address }, + selectedAddress: address, + interactiveReplacementToken: { + url: 'https://saturn-custody-ui.codefi.network/', + }, + custodyAccountDetails: { + [address]: { balance: '0x', custodianName: 'Jupiter' }, + }, + mmiConfiguration: { + custodians: [ + { + production: true, + name: 'Jupiter', + type: 'Jupiter', + iconUrl: 'iconUrl', + displayName: 'displayName', + }, + ], + }, + institutionalFeatures: { + complianceProjectId: '', + connectRequests: [ + { + labels: [ + { + key: 'service', + value: 'test', + }, + ], + origin: 'origin', + token: 'testToken', + feature: 'custodian', + service: 'Jupiter', + apiUrl: 'https://', + environment: 'Jupiter', + }, + ], + }, + }, +}; + +const store = configureStore(customData); + +export default { + title: 'Pages/Institutional/InteractiveReplacementTokenPage', + decorators: [(story) => {story()}], + component: InteractiveReplacementTokenPage, + args: { + history: { + push: action('history.push()'), + }, + }, +}; + +export const DefaultStory = (args) => ( + +); + +DefaultStory.storyName = 'InteractiveReplacementTokenPage'; diff --git a/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js new file mode 100644 index 000000000..d462f4a7a --- /dev/null +++ b/ui/pages/institutional/interactive-replacement-token-page/interactive-replacement-token-page.test.js @@ -0,0 +1,225 @@ +import React from 'react'; +import { screen, act, fireEvent, waitFor } from '@testing-library/react'; +import configureMockStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import mockState from '../../../../test/data/mock-state.json'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; +import { CHAIN_IDS } from '../../../../shared/constants/network'; +import { shortenAddress } from '../../../helpers/utils/util'; +import InteractiveReplacementTokenPage from '.'; + +const custodianAccounts = [ + { + address: '0x9d0ba4ddac06032527b140912ec808ab9451b788', + balance: '0x', + name: 'Jupiter', + labels: [ + { + key: 'service', + value: 'Label test 1', + }, + ], + }, + { + address: '0xeb9e64b93097bc15f01f13eae97015c57ab64823', + balance: '0x', + name: 'Jupiter', + labels: [ + { + key: 'service', + value: 'Label test 2', + }, + ], + }, +]; + +const mockedShowInteractiveReplacementTokenBanner = jest.fn(); + +const mockedRemoveAddTokenConnectRequest = jest + .fn() + .mockReturnValue({ type: 'TYPE' }); +const mockedSetCustodianNewRefreshToken = jest + .fn() + .mockReturnValue({ type: 'TYPE' }); +let mockedGetCustodianConnectRequest = jest + .fn() + .mockReturnValue(async () => await custodianAccounts); + +jest.mock('../../../store/institutional/institution-background', () => ({ + mmiActionsFactory: () => ({ + removeAddTokenConnectRequest: mockedRemoveAddTokenConnectRequest, + setCustodianNewRefreshToken: mockedSetCustodianNewRefreshToken, + getCustodianAccounts: mockedGetCustodianConnectRequest, + }), + showInteractiveReplacementTokenBanner: () => + mockedShowInteractiveReplacementTokenBanner, +})); + +const address = '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F'; +const custodianAddress = '0xeb9e64b93097bc15f01f13eae97015c57ab64823'; +const accountName = 'Jupiter'; +const labels = [ + { + key: 'service', + value: 'label test', + }, +]; +const connectRequests = [ + { + labels, + origin: 'origin', + apiUrl: 'apiUrl', + token: { + projectName: 'projectName', + projectId: 'projectId', + clientId: 'clientId', + }, + }, +]; + +const props = { + history: { + push: jest.fn(), + }, +}; + +const render = ({ newState } = {}) => { + const state = { + ...mockState, + metamask: { + ...mockState.metamask, + modal: { props: address }, + selectedAddress: address, + interactiveReplacementToken: { + url: 'https://saturn-custody-ui.codefi.network/', + }, + custodyAccountDetails: { + [address]: { balance: '0x', custodianName: 'Jupiter' }, + }, + mmiConfiguration: { + custodians: [ + { + production: true, + name: 'Jupiter', + type: 'Jupiter', + iconUrl: 'iconUrl', + displayName: 'displayName', + }, + ], + }, + institutionalFeatures: { + complianceProjectId: '', + connectRequests, + }, + ...newState, + }, + }; + const middlewares = [thunk]; + const mockStore = configureMockStore(middlewares); + const store = mockStore(state); + + return renderWithProvider( + , + store, + ); +}; + +describe('Interactive Replacement Token Page', function () { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render all the accounts correctly', async () => { + const expectedHref = `${ + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET] + }address/${custodianAddress}`; + + await act(async () => await render()); + + expect(screen.getByText(accountName)).toBeInTheDocument(); + const link = screen.getByRole('link', { + name: shortenAddress(custodianAddress), + }); + + expect(link).toHaveAttribute('href', expectedHref); + expect( + screen.getByText(shortenAddress(custodianAddress)), + ).toBeInTheDocument(); + expect( + screen.getByText(custodianAccounts[1].labels[0].value), + ).toBeInTheDocument(); + }); + + it('should not render if connectRequests is empty', async () => { + const newState = { + institutionalFeatures: { + connectRequests: [], + }, + }; + + const { queryByTestId } = render({ newState }); + + expect( + queryByTestId('interactive-replacement-token'), + ).not.toBeInTheDocument(); + }); + + it('should call onRemoveAddTokenConnectRequest and navigate to mostRecentOverviewPage when handleReject is called', () => { + const mostRecentOverviewPage = '/mostRecentOverviewPage'; + + const { getByText } = render(); + + fireEvent.click(getByText('Reject')); + + expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalled(); + expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalledWith({ + origin: connectRequests[0].origin, + apiUrl: connectRequests[0].apiUrl, + token: connectRequests[0].token, + }); + expect(props.history.push).toHaveBeenCalled(); + expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage); + }); + + it('should call onRemoveAddTokenConnectRequest, setCustodianNewRefreshToken, and dispatch showInteractiveReplacementTokenBanner when handleApprove is called', async () => { + const mostRecentOverviewPage = { + pathname: '/institutional-features/done', + state: { + description: + 'You can now use your custodian accounts in MetaMask Institutional.', + imgSrc: 'iconUrl', + title: 'Your custodian token has been refreshed', + }, + }; + + await act(async () => { + const { getByText } = await render(); + fireEvent.click(getByText('Approve')); + }); + + expect(mockedShowInteractiveReplacementTokenBanner).toHaveBeenCalled(); + expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalled(); + expect(mockedRemoveAddTokenConnectRequest).toHaveBeenCalledWith({ + origin: connectRequests[0].origin, + apiUrl: connectRequests[0].apiUrl, + token: connectRequests[0].token, + }); + expect(props.history.push).toHaveBeenCalled(); + expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage); + }); + + it('should reject if there are errors', async () => { + mockedGetCustodianConnectRequest = jest.fn().mockReturnValue(async () => { + throw new Error(); + }); + + await act(async () => { + const { getByText, container } = await render(); + fireEvent.click(getByText('Approve')); + await waitFor(() => { + expect(container).toMatchSnapshot(); + }); + }); + }); +}); diff --git a/ui/pages/keychains/reveal-seed.js b/ui/pages/keychains/reveal-seed.js index 54633840f..81c264abc 100644 --- a/ui/pages/keychains/reveal-seed.js +++ b/ui/pages/keychains/reveal-seed.js @@ -28,7 +28,7 @@ import { Button, TextField, HelpText, - BUTTON_TYPES, + BUTTON_VARIANT, TEXT_FIELD_SIZES, TEXT_FIELD_TYPES, BUTTON_SIZES, @@ -148,9 +148,39 @@ const RevealSeedPage = () => { }; const renderRevealSeedContent = () => { + // default for SRP_VIEW_SRP_TEXT event because this is the first thing shown after rendering + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpViewSrpText, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + return (
- + { + if (tabName === 'text-seed') { + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpViewSrpText, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + } else if (tabName === 'qr-seed') { + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpViewsSrpQR, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + }, + }); + } + }} + > { copy_method: 'clipboard', }, }); + trackEvent({ + category: MetaMetricsEventCategory.Keys, + event: MetaMetricsEventName.SrpCopiedToClipboard, + properties: { + key_type: MetaMetricsEventKeyType.Srp, + copy_method: 'clipboard', + }, + }); }} /> @@ -202,7 +240,7 @@ const RevealSeedPage = () => { @@ -278,7 +339,7 @@ const RevealSeedPage = () => { {t('revealSeedWordsDescription1', [ ) : ( @@ -130,11 +130,11 @@ export default class DomainInput extends Component { )}
) : ( @@ -160,9 +160,7 @@ export default class DomainInput extends Component { this.props.scanQrCode(); } }} - iconName={ - userInput ? ICON_NAMES.CLOSE : ICON_NAMES.SCAN_BARCODE - } + iconName={userInput ? IconName.Close : IconName.ScanBarcode} ariaLabel={t(userInput ? 'close' : 'scanQrCode')} color={ userInput ? IconColor.iconDefault : IconColor.primaryDefault diff --git a/ui/pages/send/send.test.js b/ui/pages/send/send.test.js index ffe97670f..5f73a700b 100644 --- a/ui/pages/send/send.test.js +++ b/ui/pages/send/send.test.js @@ -93,7 +93,7 @@ const baseStore = { useNativeCurrencyAsPrimaryCurrency: false, }, currentCurrency: 'USD', - provider: { + providerConfig: { chainId: CHAIN_IDS.GOERLI, }, nativeCurrency: 'ETH', diff --git a/ui/pages/settings/advanced-tab/advanced-tab.component.js b/ui/pages/settings/advanced-tab/advanced-tab.component.js index 10c63fd27..837eb0d0d 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.component.js @@ -25,6 +25,11 @@ import { import { exportAsFile } from '../../../helpers/utils/export-utils'; import ActionableMessage from '../../../components/ui/actionable-message'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; +import { BannerAlert } from '../../../components/component-library'; +import { + SEVERITIES, + TextVariant, +} from '../../../helpers/constants/design-system'; const CORRUPT_JSON_FILE = 'CORRUPT_JSON_FILE'; @@ -40,6 +45,7 @@ export default class AdvancedTab extends PureComponent { setHexDataFeatureFlag: PropTypes.func, displayWarning: PropTypes.func, showResetAccountConfirmationModal: PropTypes.func, + showEthSignModal: PropTypes.func, warning: PropTypes.string, sendHexData: PropTypes.bool, showFiatInTestnets: PropTypes.bool, @@ -59,7 +65,7 @@ export default class AdvancedTab extends PureComponent { disabledRpcMethodPreferences: PropTypes.shape({ eth_sign: PropTypes.bool.isRequired, }), - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled: PropTypes.bool, ///: END:ONLY_INCLUDE_IN }; @@ -407,12 +413,12 @@ export default class AdvancedTab extends PureComponent { ledgerTransportType, setLedgerTransportPreference, userHasALedgerAccount, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN } = this.props; - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) if (desktopEnabled) { return null; } @@ -539,10 +545,23 @@ export default class AdvancedTab extends PureComponent { } renderToggleEthSignControl() { - const { t } = this.context; - const { disabledRpcMethodPreferences, setDisabledRpcMethodPreference } = - this.props; - + const { t, trackEvent } = this.context; + const { + disabledRpcMethodPreferences, + showEthSignModal, + setDisabledRpcMethodPreference, + } = this.props; + const toggleOff = (value) => { + setDisabledRpcMethodPreference('eth_sign', !value); + trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.OnboardingWalletAdvancedSettings, + properties: { + location: 'Settings', + enable_eth_sign: false, + }, + }); + }; return (
+ + {disabledRpcMethodPreferences?.eth_sign === true ? ( + + {t('toggleEthSignBannerDescription')} + + ) : null}
- setDisabledRpcMethodPreference('eth_sign', !value) - } - offLabel={t('off')} - onLabel={t('on')} + onToggle={(value) => { + value ? toggleOff(value) : showEthSignModal(); + }} + offLabel={t('toggleEthSignOff')} + onLabel={t('toggleEthSignOn')} />
diff --git a/ui/pages/settings/advanced-tab/advanced-tab.container.js b/ui/pages/settings/advanced-tab/advanced-tab.container.js index 95ce14e4a..539e60b33 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.container.js @@ -30,7 +30,7 @@ export const mapStateToProps = (state) => { useNonceField, ledgerTransportType, dismissSeedBackUpReminder, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN } = metamask; @@ -53,7 +53,7 @@ export const mapStateToProps = (state) => { dismissSeedBackUpReminder, userHasALedgerAccount, disabledRpcMethodPreferences, - ///: BEGIN:ONLY_INCLUDE_IN(flask) + ///: BEGIN:ONLY_INCLUDE_IN(desktop) desktopEnabled, ///: END:ONLY_INCLUDE_IN }; @@ -68,6 +68,7 @@ export const mapDispatchToProps = (dispatch) => { displayWarning: (warning) => dispatch(displayWarning(warning)), showResetAccountConfirmationModal: () => dispatch(showModal({ name: 'CONFIRM_RESET_ACCOUNT' })), + showEthSignModal: () => dispatch(showModal({ name: 'ETH_SIGN' })), setUseNonceField: (value) => dispatch(setUseNonceField(value)), setShowFiatConversionOnTestnetsPreference: (value) => { return dispatch(setShowFiatConversionOnTestnetsPreference(value)); diff --git a/ui/pages/settings/advanced-tab/advanced-tab.stories.js b/ui/pages/settings/advanced-tab/advanced-tab.stories.js index a6c3f7eb2..b15bb9edb 100644 --- a/ui/pages/settings/advanced-tab/advanced-tab.stories.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.stories.js @@ -27,6 +27,9 @@ export default { showResetAccountConfirmationModal: { action: 'showResetAccountConfirmationModal', }, + showEthSignModal: { + action: 'showEthSignModal', + }, }, }; diff --git a/ui/pages/settings/contact-list-tab/add-contact/add-contact.test.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.test.js index 2cc5234de..29f9fc772 100644 --- a/ui/pages/settings/contact-list-tab/add-contact/add-contact.test.js +++ b/ui/pages/settings/contact-list-tab/add-contact/add-contact.test.js @@ -10,7 +10,7 @@ describe('AddContact component', () => { const middleware = [thunk]; const state = { metamask: { - provider: { + providerConfig: { type: 'mainnet', nickname: '', }, diff --git a/ui/pages/settings/contact-list-tab/contact-list-tab.component.js b/ui/pages/settings/contact-list-tab/contact-list-tab.component.js index 46d3155bc..02cce6a37 100644 --- a/ui/pages/settings/contact-list-tab/contact-list-tab.component.js +++ b/ui/pages/settings/contact-list-tab/contact-list-tab.component.js @@ -13,10 +13,10 @@ import { } from '../../../helpers/utils/settings-search'; import { Icon, - ICON_NAMES, - ICON_SIZES, -} from '../../../components/component-library/icon/deprecated'; -import { Color } from '../../../helpers/constants/design-system'; + IconName, + IconSize, +} from '../../../components/component-library'; +import { IconColor } from '../../../helpers/constants/design-system'; import EditContact from './edit-contact'; import AddContact from './add-contact'; import ViewContact from './view-contact'; @@ -79,10 +79,10 @@ export default class ContactListTab extends Component {

{t('buildContactList')}

diff --git a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js index bf29852f4..72cb08479 100644 --- a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js @@ -2,6 +2,7 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBookEntry } from '../../../../selectors'; +import { getProviderConfig } from '../../../../ducks/metamask/metamask'; import { CONTACT_VIEW_ROUTE, CONTACT_LIST_ROUTE, @@ -25,7 +26,7 @@ const mapStateToProps = (state, ownProps) => { getAddressBookEntry(state, address) || state.metamask.identities[address]; const { memo, name } = contact || {}; - const { chainId } = state.metamask.provider; + const { chainId } = getProviderConfig(state); return { address: contact ? address : null, diff --git a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.test.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.test.js index 1853a4de1..dcb13d871 100644 --- a/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.test.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.test.js @@ -10,7 +10,7 @@ describe('AddContact component', () => { const middleware = [thunk]; const state = { metamask: { - provider: { + providerConfig: { type: 'mainnet', nickname: '', }, diff --git a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js index 8a28efe00..5045b9565 100644 --- a/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js +++ b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js @@ -4,12 +4,12 @@ import { Redirect } from 'react-router-dom'; import Identicon from '../../../../components/ui/identicon'; import Button from '../../../../components/ui/button/button.component'; -import { - ICON_NAMES, - ICON_SIZES, -} from '../../../../components/component-library/icon/deprecated'; -import { ButtonIcon } from '../../../../components/component-library/button-icon/deprecated'; +import { + ButtonIcon, + ButtonIconSize, + IconName, +} from '../../../../components/component-library'; import Tooltip from '../../../../components/ui/tooltip'; import { useI18nContext } from '../../../../hooks/useI18nContext'; @@ -74,8 +74,8 @@ function ViewContact({ onClick={() => { handleCopy(checkSummedAddress); }} - iconName={copied ? ICON_NAMES.COPY_SUCCESS : ICON_NAMES.COPY} - size={ICON_SIZES.LG} + iconName={copied ? IconName.CopySuccess : IconName.Copy} + size={ButtonIconSize.Lg} color={IconColor.primaryDefault} /> diff --git a/ui/pages/settings/experimental-tab/__snapshots__/experimental-tab.test.js.snap b/ui/pages/settings/experimental-tab/__snapshots__/experimental-tab.test.js.snap index 940e72647..81a8427b6 100644 --- a/ui/pages/settings/experimental-tab/__snapshots__/experimental-tab.test.js.snap +++ b/ui/pages/settings/experimental-tab/__snapshots__/experimental-tab.test.js.snap @@ -17,7 +17,7 @@ exports[`ExperimentalTab with desktop enabled renders ExperimentalTab component class="settings-page__content-item" > - Enable transaction security providers + Enable security alerts

- OpenSea (Beta) + OpenSea + Blockaid (Beta)