├── test ├── resources │ ├── test-2.yaml │ ├── test-8.yaml │ ├── test-7.yaml-crypt │ ├── test-6.yaml-crypt │ ├── test-4.yaml-crypt │ ├── test-3.yaml-crypt │ ├── test-1b.yaml-crypt │ ├── test-5.yaml-crypt │ ├── test-1a.yaml-crypt │ └── test-2.yaml-crypt ├── crypto-util.js ├── yaml-crypt-helper-test.js ├── utils-test.js ├── crypto-test.js ├── yaml-crypt-test.js └── yaml-crypt-cli-test.js ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ └── build.yml ├── .eslintrc.json ├── lib ├── yaml-crypt-helper.js ├── utils.js ├── index.d.ts ├── crypto.js └── yaml-crypt.js ├── LICENSE ├── package.json ├── README.md ├── bin └── yaml-crypt-cli.js └── yarn.lock /test/resources/test-2.yaml: -------------------------------------------------------------------------------- 1 | first: Hello, world! 2 | second: Hello! 3 | --- 4 | other: Hello, world! 5 | -------------------------------------------------------------------------------- /test/resources/test-8.yaml: -------------------------------------------------------------------------------- 1 | b1: true 2 | b2: false 3 | n1: 123 4 | n2: -0.5 5 | u1: null 6 | s1: str 7 | -------------------------------------------------------------------------------- /test/resources/test-7.yaml-crypt: -------------------------------------------------------------------------------- 1 | 6IBKJKlQLWHGGrWg4UlkTnUoRLebBK70DBmAY6vK3jVa7orWjHr0ZsjCl8E9YGFsFgYy6 2 | -------------------------------------------------------------------------------- /test/resources/test-6.yaml-crypt: -------------------------------------------------------------------------------- 1 | text: ! 6IBKJKlQLWHGGrWg4UlkTnUoRLebBK70DBmAY6vK3jVa7orWjHr0ZsjCl8E9YGFsFgYy6 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | !.eslintrc.json 4 | !.travis.yml 5 | 6 | *.log 7 | *.yml 8 | *.yaml 9 | 10 | node_modules/ 11 | coverage/ 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /test/resources/test-4.yaml-crypt: -------------------------------------------------------------------------------- 1 | base64: ! >- 2 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD99Go9wdFY16X9GGXSVND43-vV0cCk8Y-xZHJCgfl5TEkfT0vXuXMHEH88mfQ491BhQQd2kc0ZNxHaMSR94ZZGQ= 3 | -------------------------------------------------------------------------------- /test/resources/test-3.yaml-crypt: -------------------------------------------------------------------------------- 1 | a: 2 | b: 3 | c: ! >- 4 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0ODxwF4kD5PwYVPv70wJaVzzcHQW-05aGCmKbqm5Xr_JU-zzrnTJPuTgugtPGENImYqA== 5 | x: plain 6 | -------------------------------------------------------------------------------- /test/resources/test-1b.yaml-crypt: -------------------------------------------------------------------------------- 1 | key1: ! >- 2 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg== 3 | key2: ! XUvrtHkyXTh1VUW885Ta4V5eQ3hBMFQMC3S3QwEfWzKWVDt3A5TnVUNtVXubi0fsAA8eerahpobwC8 4 | -------------------------------------------------------------------------------- /test/resources/test-5.yaml-crypt: -------------------------------------------------------------------------------- 1 | nested: 2 | object: 3 | - with: 1 4 | - some: 2 5 | - array: 6 | values: 7 | str: ! >- 8 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0ODzjOnkJEZ7hHk5YOIQNxL8_PdTDxFii3sQCqTs72_cSdXWEMD25WBeAD_cXFu3x_MQ== 9 | -------------------------------------------------------------------------------- /test/resources/test-1a.yaml-crypt: -------------------------------------------------------------------------------- 1 | key1: ! >- 2 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg== 3 | key2: ! >- 4 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg== 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 8, 4 | "sourceType": "module" 5 | }, 6 | "extends": ["eslint:recommended"], 7 | "env": { 8 | "node": true, 9 | "es6": true 10 | }, 11 | "rules": { 12 | "semi": "error", 13 | "no-tabs": "error", 14 | "no-console": "warn", 15 | "no-constant-condition": "off" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v2 12 | with: 13 | node-version: "14" 14 | - run: yarn 15 | - uses: coverallsapp/github-action@master 16 | with: 17 | github-token: "${{secrets.GITHUB_TOKEN}}" 18 | -------------------------------------------------------------------------------- /test/resources/test-2.yaml-crypt: -------------------------------------------------------------------------------- 1 | first: ! >- 2 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg== 3 | second: ! >- 4 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0ODzjOnkJEZ7hHk5YOIQNxL8_PdTDxFii3sQCqTs72_cSdXWEMD25WBeAD_cXFu3x_MQ== 5 | --- 6 | other: ! >- 7 | gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg== 8 | -------------------------------------------------------------------------------- /lib/yaml-crypt-helper.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | function walk(dir, recursive, callback) { 5 | const files = fs.readdirSync(dir); 6 | for (const file of files) { 7 | const p = path.resolve(dir, file); 8 | const stat = fs.statSync(p); 9 | if (stat.isDirectory()) { 10 | if (recursive) { 11 | walk(p, true, callback); 12 | } 13 | } else { 14 | callback(p); 15 | } 16 | } 17 | } 18 | 19 | module.exports.walk = walk; 20 | -------------------------------------------------------------------------------- /test/crypto-util.js: -------------------------------------------------------------------------------- 1 | const fernet = require("fernet"); 2 | const branca = require("branca"); 3 | 4 | /** 5 | * Ensures the crypto calls are reproducible 6 | */ 7 | function setupCrypto() { 8 | // Fernet: 9 | const setIV = fernet.Token.prototype.setIV; 10 | fernet.Token.prototype.setIV = function () { 11 | const iv = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 12 | setIV.apply(this, [iv]); 13 | }; 14 | const setTime = fernet.Token.prototype.setTime; 15 | fernet.Token.prototype.setTime = function () { 16 | setTime.apply(this, [1000]); 17 | }; 18 | } 19 | 20 | function decryptBranca(key, msg) { 21 | return branca(Buffer.from(key)).decode(msg).toString(); 22 | } 23 | 24 | module.exports = { setupCrypto, decryptBranca }; 25 | -------------------------------------------------------------------------------- /test/yaml-crypt-helper-test.js: -------------------------------------------------------------------------------- 1 | const mocha = require("mocha"); 2 | const describe = mocha.describe; 3 | const it = mocha.it; 4 | const chai = require("chai"); 5 | const expect = chai.expect; 6 | 7 | const { walk } = require("../lib/yaml-crypt-helper"); 8 | 9 | describe("yaml-crypt-helper", () => { 10 | it("should throw an error", () => { 11 | expect(() => walk("./nonexistent", () => {})).to.throw(/ENOENT/); 12 | }); 13 | 14 | it("should walk the directory", () => { 15 | const files = []; 16 | const callback = file => files.push(file); 17 | walk("./test", false, callback); 18 | expect(files).to.have.lengthOf(6); 19 | }); 20 | 21 | it("should walk the directory recursively", () => { 22 | const files = []; 23 | const callback = file => files.push(file); 24 | walk("./test", true, callback); 25 | expect(files).to.have.lengthOf(16); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2017 Pascal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/utils-test.js: -------------------------------------------------------------------------------- 1 | const mocha = require("mocha"); 2 | const describe = mocha.describe; 3 | const it = mocha.it; 4 | const chai = require("chai"); 5 | const expect = chai.expect; 6 | 7 | const utils = require("../lib/utils"); 8 | 9 | describe("utils", () => { 10 | it("should throw an error when no key is given", () => { 11 | expect(() => utils.tryDecrypt()).to.throw(/no decryption keys given/); 12 | }); 13 | 14 | it("should split the path", () => { 15 | expect(utils.splitPath("a.b")).to.deep.equal(["a", "b"]); 16 | expect(utils.splitPath("a.b.c")).to.deep.equal(["a", "b", "c"]); 17 | expect(utils.splitPath("a.'b'")).to.deep.equal(["a", "b"]); 18 | expect(utils.splitPath('"a".b')).to.deep.equal(["a", "b"]); 19 | expect(utils.splitPath('"a.b".c')).to.deep.equal(["a.b", "c"]); 20 | expect(utils.splitPath("ab.cd[ef].gh")).to.deep.equal([ 21 | "ab", 22 | "cd", 23 | "ef", 24 | "gh" 25 | ]); 26 | expect(utils.splitPath("a.b.'a.b'[a..s][a..]")).to.deep.equal([ 27 | "a", 28 | "b", 29 | "a.b", 30 | "a..s", 31 | "a.." 32 | ]); 33 | }); 34 | 35 | it("should return an error when splitting an invalid path", () => { 36 | expect(() => utils.splitPath("a.b[")).to.throw(/unmatched separator/); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yaml-crypt", 3 | "version": "0.7.8", 4 | "description": "Encrypt and decrypt YAML documents", 5 | "license": "MIT", 6 | "author": "Pascal", 7 | "homepage": "https://github.com/autoapply/yaml-crypt", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/autoapply/yaml-crypt.git" 11 | }, 12 | "main": "./lib/yaml-crypt.js", 13 | "types": "./lib/index.d.ts", 14 | "bin": { 15 | "yaml-crypt": "./bin/yaml-crypt-cli.js" 16 | }, 17 | "scripts": { 18 | "lint": "eslint . && prettier -l */**.js */**.ts", 19 | "test": "nyc mocha --timeout=8000 --check-leaks", 20 | "test:coverage": "nyc --reporter=lcov mocha", 21 | "build": "yarn lint && yarn test:coverage", 22 | "prepublish": "yarn build" 23 | }, 24 | "dependencies": { 25 | "argparse": "^2.0.1", 26 | "branca": "^0.5.0", 27 | "fernet": "^0.4.0", 28 | "js-yaml": "^4.1.0", 29 | "pkginfo": "^0.4.1", 30 | "tmp": "^0.2.1", 31 | "urlsafe-base64": "^1.0.0" 32 | }, 33 | "devDependencies": { 34 | "chai": "^4.3.10", 35 | "coveralls": "^3.1.1", 36 | "eslint": "^8.55.0", 37 | "mocha": "^10.2.0", 38 | "nyc": "^15.1.0", 39 | "prettier": "^3.1.1" 40 | }, 41 | "prettier": { 42 | "trailingComma": "none", 43 | "arrowParens": "avoid" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yaml-crypt 2 | 3 | [![Coverage status](https://img.shields.io/coveralls/github/autoapply/yaml-crypt.svg?style=flat-square)](https://coveralls.io/github/autoapply/yaml-crypt) 4 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) 5 | 6 | Command line utility to encrypt and decrypt YAML documents. 7 | 8 | ## Installation 9 | 10 | The package is available on the [npm registry](https://www.npmjs.com/package/yaml-crypt), so just run 11 | 12 | $ yarn global add yaml-crypt 13 | $ yaml-crypt -h 14 | 15 | You can also install the package locally: 16 | 17 | $ mkdir yaml-crypt && cd yaml-crypt 18 | $ yarn init --yes 19 | $ yarn add yaml-crypt 20 | $ ./node_modules/.bin/yaml-crypt -h 21 | 22 | ## Usage 23 | 24 | First you will need to generate a key file. Currently, 25 | both [Fernet](https://github.com/fernet/spec/blob/master/Spec.md) 26 | and [Branca](https://branca.io/) encryption schemes are supported. 27 | 28 | To generate a new random key, run 29 | 30 | $ yaml-crypt --generate-key > my-key-file 31 | 32 | To encrypt all values in a YAML file, run 33 | 34 | $ yaml-crypt -k my-key-file my-file.yaml 35 | 36 | This will encrypt the file contents and rename the file to `my-file.yaml-crypt`. 37 | 38 | The operation will be performed based on the file extension, so to decrypt a file, 39 | just use 40 | 41 | $ yaml-crypt -k my-key-file my-file.yaml-crypt 42 | 43 | To specify an explicit operation, use `-e` or `-d` for encryption or decryption. 44 | 45 | You can also encrypt only certain parts of a file. Given the following YAML file 46 | 47 | ```yaml 48 | apiVersion: v1 49 | kind: Secret 50 | data: 51 | username: user1 52 | password: secret123 53 | ``` 54 | 55 | you can use `--path data` to only encrypt the values `user1` and `secret123`. 56 | 57 | >[Kubernetes](https://kubernetes.io/) secrets are Base64 encoded, 58 | >so you should also use the `--base64` (or `-B`) option. 59 | 60 | It is also possible to directly open encrypted files in an editor, decrypting them 61 | before opening and encrypting again when saving: 62 | 63 | $ yaml-crypt -E my-file.yaml-crypt 64 | 65 | When editing, you can add new encrypted data by specifying the yaml tag ``: 66 | 67 | ```yaml 68 | unencrypted: 69 | hello: world 70 | encrypted: 71 | key1: ! secret-key-1 72 | # add the following line to add a new encrypted entry "key2" to the file, 73 | # which will be encrypted in the yaml-crypt file: 74 | key2: ! secret123 75 | ``` 76 | 77 | ## Configuration 78 | 79 | The yaml-crypt command looks in `~/.yaml-crypt` for a file `config.yaml` or `config.yml`. 80 | Currently, only the `keys` property is supported. These keys will be used when no keys 81 | are given on the command line: 82 | 83 | $ cat ~/.yaml-crypt/config.yaml 84 | keys: 85 | - key: my-raw-key-data 86 | - key: !!binary my-base64-key-data 87 | $ yaml-crypt my-file.yaml 88 | 89 | All whitespaces at the beginning and end of keys will be removed when reading keys. 90 | 91 | ## Related projects 92 | 93 | - https://github.com/mozilla/sops 94 | - https://github.com/huwtl/secure_yaml 95 | - https://github.com/StackExchange/blackbox 96 | - https://github.com/bitnami-labs/sealed-secrets 97 | 98 | ## License 99 | 100 | The yaml-crypt tool is licensed under the MIT License 101 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | const yaml = require("js-yaml"); 2 | 3 | class UsageError extends Error {} 4 | 5 | function dump(obj, opts) { 6 | return yaml 7 | .dump(obj, opts) 8 | .replace(/!yaml-crypt\/([a-zA-Z0-9:]+)/g, "!"); 9 | } 10 | 11 | function dumpAll(objs, opts) { 12 | let str = ""; 13 | for (let idx = 0; idx < objs.length; idx++) { 14 | if (idx > 0) { 15 | str += "---\n"; 16 | } 17 | str += dump(objs[idx], opts); 18 | } 19 | return str; 20 | } 21 | 22 | function loadAll(str, opts) { 23 | // see https://github.com/nodeca/js-yaml/pull/381 24 | const objs = []; 25 | yaml.loadAll(str, obj => objs.push(obj), opts); 26 | return objs; 27 | } 28 | 29 | function splitPath(path) { 30 | const parts = []; 31 | const defaults = new RegExp(/(\."|\.'|\[|\.)/); 32 | let str = path[0] === '"' || path[0] === "'" ? "." + path : path; 33 | let next = defaults; 34 | while (str.length > 0) { 35 | const m = str.match(next); 36 | if (m == null) { 37 | break; 38 | } else { 39 | if (m.index > 0) { 40 | parts.push(str.substring(0, m.index)); 41 | } 42 | const sep = m[0]; 43 | if (sep === '."') { 44 | next = /"/; 45 | } else if (sep === ".'") { 46 | next = /'/; 47 | } else if (sep === "[") { 48 | next = /\]/; 49 | } else { 50 | next = defaults; 51 | } 52 | str = str.substring(m.index + sep.length); 53 | } 54 | } 55 | if (next === defaults) { 56 | if (str.length > 0) { 57 | parts.push(str); 58 | } 59 | return parts; 60 | } else { 61 | throw new Error("unmatched separator: " + next); 62 | } 63 | } 64 | 65 | function walkStringValues(obj, path, callback) { 66 | walkValues(obj, path, v => typeof v === "string", callback); 67 | } 68 | 69 | function walkValues(obj, path, check, callback) { 70 | let subobj = obj; 71 | if (path) { 72 | const parts = splitPath(path); 73 | for (let idx = 0; idx < parts.length; idx++) { 74 | const part = parts[idx]; 75 | if (idx === parts.length - 1 && check(subobj[part])) { 76 | subobj[part] = callback(subobj[part]); 77 | return; 78 | } else { 79 | subobj = subobj[part]; 80 | } 81 | } 82 | } 83 | for (const key in subobj) { 84 | if (Object.prototype.hasOwnProperty.call(subobj, key)) { 85 | const value = subobj[key]; 86 | if (check(value)) { 87 | subobj[key] = callback(value); 88 | } else if (typeof value === "object") { 89 | walkValues(value, null, check, callback); 90 | } 91 | } 92 | } 93 | } 94 | 95 | function tryDecrypt(algorithms, keys, decrypt) { 96 | if (!keys || !keys.length) { 97 | throw new UsageError("cannot decrypt data, no decryption keys given!"); 98 | } 99 | let result = null; 100 | for (const algorithm of algorithms) { 101 | for (const key of keys) { 102 | try { 103 | const decrypted = decrypt(algorithm, key); 104 | result = { key, algorithm, decrypted }; 105 | break; 106 | } catch (e) { 107 | continue; 108 | } 109 | } 110 | } 111 | if (result != null) { 112 | return result; 113 | } else { 114 | throw new UsageError("no matching key to decrypt the given data!"); 115 | } 116 | } 117 | 118 | module.exports = { 119 | UsageError, 120 | dump, 121 | dumpAll, 122 | loadAll, 123 | splitPath, 124 | walkValues, 125 | walkStringValues, 126 | tryDecrypt 127 | }; 128 | -------------------------------------------------------------------------------- /test/crypto-test.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const mocha = require("mocha"); 4 | const describe = mocha.describe; 5 | const it = mocha.it; 6 | const chai = require("chai"); 7 | const expect = chai.expect; 8 | 9 | const crypto = require("../lib/crypto"); 10 | const { setupCrypto, decryptBranca } = require("./crypto-util"); 11 | 12 | setupCrypto(); 13 | 14 | describe("crypto", () => { 15 | it("should return the encrypted content (fernet)", () => { 16 | const result = crypto.encrypt( 17 | "fernet", 18 | "aehae5Ui0Eechaeghau9Yoh9jufiep7H", 19 | "Hello, world!" 20 | ); 21 | expect(result).to.equal( 22 | "gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg==" 23 | ); 24 | }); 25 | 26 | it("should return the encrypted content (branca)", () => { 27 | const key = "aehae5Ui0Eechaeghau9Yoh9jufiep7H"; 28 | const result = crypto.encrypt("branca", key, "Hello, world!"); 29 | expect(result).to.be.not.empty; 30 | expect(decryptBranca(key, result)).to.equal("Hello, world!"); 31 | }); 32 | 33 | it("should generate a key (branca)", () => { 34 | const result = crypto.generateKey("branca"); 35 | expect(result).to.have.lengthOf(32); 36 | }); 37 | 38 | it("should throw an error when passing null", () => { 39 | expect(() => crypto.decrypt("fernet", "", null)).to.throw( 40 | /message is null/ 41 | ); 42 | }); 43 | 44 | it("should throw an error when passing invalid data", () => { 45 | expect(() => crypto.decrypt("fernet", "", {})).to.throw( 46 | /invalid type for message/ 47 | ); 48 | }); 49 | 50 | it("should throw an error when passing invalid algorithm", () => { 51 | expect(() => crypto.decrypt("x", "", "")).to.throw(/unknown algorithm/); 52 | }); 53 | 54 | it("should return the decrypted content (fernet)", () => { 55 | const key = "aehae5Ui0Eechaeghau9Yoh9jufiep7H"; 56 | const encrypted = 57 | "gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg=="; 58 | expect(crypto.decrypt("fernet", key, encrypted)).to.equal("Hello, world!"); 59 | }); 60 | 61 | it("should return the decrypted content (branca)", () => { 62 | const key = "aehae5Ui0Eechaeghau9Yoh9jufiep7H"; 63 | const encrypted = 64 | "XUvrtHkyXTh1VUW885Ta4V5eQ3hBMFQMC3S3QwEfWzKWVDt3A5TnVUNtVXubi0fsAA8eerahpobwC8"; 65 | expect(crypto.decrypt("branca", key, encrypted)).to.equal("Hello, world!"); 66 | }); 67 | 68 | it("should correctly identify valid tokens (fernet)", () => { 69 | expect(crypto.isToken("gAAAAAAAAAA")).to.equal(true); 70 | expect(crypto.isToken("gBBBB")).to.equal(true); 71 | }); 72 | 73 | it("should correctly identify valid Buffer tokens (fernet)", () => { 74 | expect(crypto.isToken(Buffer.from("gAAAAAAAAAA"))).to.equal(true); 75 | expect(crypto.isToken(Buffer.from("gBBBB"))).to.equal(true); 76 | }); 77 | 78 | it("should correctly identify valid string tokens (branca)", () => { 79 | const token = fs 80 | .readFileSync("./test/resources/test-7.yaml-crypt") 81 | .toString(); 82 | expect(crypto.isToken(token)).to.equal(true); 83 | }); 84 | 85 | it("should correctly identify valid Buffer tokens (branca)", () => { 86 | const token = fs.readFileSync("./test/resources/test-7.yaml-crypt"); 87 | expect(crypto.isToken(token)).to.equal(true); 88 | }); 89 | 90 | it("should correctly identify invalid tokens", () => { 91 | expect(crypto.isToken("X")).to.equal(false); 92 | expect(crypto.isToken("XXX")).to.equal(false); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export as namespace yamlcrypt; 2 | 3 | export const algorithms: Algorithm[]; 4 | 5 | /** 6 | * Generates a random key to be used with the given algorithm 7 | * 8 | * @param algorithm One of "fernet" (default) or "branca" 9 | * @returns A generated key, as string, suitable for the given algorithm 10 | */ 11 | export function generateKey(algorithm?: Algorithm): string; 12 | 13 | /** 14 | * Loads the YAML file as object from the specified path, 15 | * using decryption keys from the user's configuration file 16 | * 17 | * @param path File path 18 | * @param opts Options to use while loading (optional) 19 | * @returns A promise that resolves to the loaded YAML document, as object 20 | */ 21 | export function loadFile(path: string, opts?: LoadFileOptions): Promise; 22 | 23 | export interface LoadFileOptions { 24 | /** Default decryption and encryption keys */ 25 | config?: Config; 26 | 27 | /** Needs to be specified when the YAML file contains multiple documents */ 28 | loadAll?: boolean; 29 | } 30 | 31 | /** 32 | * Load the user's configuration file from disk 33 | * 34 | * @param opts Options to use while loading (optional) 35 | * @returns A promise that resolves to the configuration object 36 | */ 37 | export function loadConfig(opts?: LoadConfigOptions): Promise; 38 | 39 | export interface LoadConfigOptions { 40 | /** Full path of the configuration file */ 41 | path?: string; 42 | 43 | /** Override user's HOME directory when loading */ 44 | home?: string; 45 | } 46 | 47 | export function yamlcrypt(opts?: YamlcryptOptions): Yamlcrypt; 48 | 49 | export type Algorithm = "fernet:0x80" | "fernet" | "branca:0xBA" | "branca"; 50 | 51 | export interface Config extends YamlcryptOptions {} 52 | 53 | export interface YamlcryptOptions { 54 | keys?: Key | Key[]; 55 | encryptionKey?: Key; 56 | } 57 | 58 | export type Key = 59 | | string 60 | | { 61 | key: string; 62 | name?: string; 63 | }; 64 | 65 | export interface Yamlcrypt { 66 | /** 67 | * Encrypts the given YAML document 68 | * 69 | * @param str The YAML document (as string) to encrypt 70 | * @param opts Encryption options 71 | * @returns The encrypted document, as string 72 | */ 73 | encrypt(str: string, opts?: EncryptOptions): string; 74 | 75 | /** 76 | * Encrypts all the given YAML documents (multiple documents 77 | * are separated by "---") 78 | * 79 | * @param str The YAML documents (as string) to encrypt 80 | * @param opts Encryption options 81 | * @returns The encrypted documents, as string 82 | */ 83 | encryptAll(str: string, opts?: EncryptOptions): string; 84 | 85 | /** 86 | * Decrypts the given YAML document, returns the parsed object 87 | * 88 | * @param str The YAML document (as string) to decrypt 89 | * @param opts Decryption options 90 | * @returns The decrypted document, as object 91 | */ 92 | decrypt(str: string, opts?: DecryptOptions): any; 93 | 94 | /** 95 | * Decrypts all the given YAML documents (separated by "---"), 96 | * returns an array of parsed objects 97 | * 98 | * @param str The YAML documents (as string) to decrypt 99 | * @param opts Decryption options 100 | * @returns Array of the decrypted documents 101 | */ 102 | decryptAll(str: string, opts?: DecryptOptions): any[]; 103 | 104 | transform( 105 | str: string, 106 | callback: (string) => string, 107 | opts?: EncryptOptions & DecryptOptions 108 | ): string; 109 | } 110 | 111 | export interface EncryptOptions { 112 | encryptionKey?: string; 113 | algorithm?: Algorithm; 114 | raw?: boolean; 115 | base64?: boolean; 116 | } 117 | 118 | export interface DecryptOptions { 119 | keys?: string[]; 120 | base64?: boolean; 121 | } 122 | -------------------------------------------------------------------------------- /lib/crypto.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | 3 | const URLSafeBase64 = require("urlsafe-base64"); 4 | const fernet = require("fernet"); 5 | const branca = require("branca"); 6 | 7 | const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 8 | const base62 = require("base-x")(BASE62); 9 | 10 | const ALGORITHM_FERNET = "fernet:0x80"; 11 | const ALGORITHM_BRANCA = "branca:0xBA"; 12 | 13 | const DEFAULT_ALGORITHM = ALGORITHM_FERNET; 14 | 15 | const algorithmHandlers = { 16 | [ALGORITHM_FERNET]: { 17 | generateKey: fernetGenerateKey, 18 | encrypt: fernetEncrypt, 19 | decrypt: fernetDecrypt 20 | }, 21 | [ALGORITHM_BRANCA]: { 22 | generateKey: brancaGenerateKey, 23 | encrypt: brancaEncrypt, 24 | decrypt: brancaDecrypt 25 | } 26 | }; 27 | 28 | const algorithms = [ALGORITHM_FERNET, ALGORITHM_BRANCA]; 29 | 30 | const __brancaDefaults = { 31 | ts: undefined, 32 | nonce: undefined 33 | }; 34 | 35 | /** 36 | * Check if the given data is a valid token 37 | * @param {string|Buffer} data Data to check 38 | * @returns {boolean} If the given data is a valid token 39 | */ 40 | function isToken(data) { 41 | if (typeof data === "string") { 42 | if (data.length > 2) { 43 | if (data[0] === "g" && data[1].match(/[a-zA-Z0-9]/)) { 44 | return Buffer.from(data.substr(0, 2), "base64")[0] === 0x80; 45 | } else { 46 | const str = data.trimRight(); 47 | if (str.match(/^[a-zA-Z0-9]+$/)) { 48 | const result = base62.decodeUnsafe(str); 49 | return result != null && result[0] === 0xba; 50 | } 51 | } 52 | } 53 | } else if (Buffer.isBuffer(data)) { 54 | if (data.length > 2 && data[0] === "g".charCodeAt(0)) { 55 | const buf = Buffer.from(data.slice(0, 2).toString("ascii"), "base64"); 56 | if (buf[0] === 0x80) { 57 | return true; 58 | } 59 | } 60 | try { 61 | const str = data.toString("ascii").trimRight(); 62 | const result = base62.decodeUnsafe(str); 63 | return result != null && result[0] === 0xba; 64 | } catch (e) { 65 | // ignore error! 66 | } 67 | } 68 | return false; 69 | } 70 | 71 | /** 72 | * Generate a new random key 73 | * @param {string} algorithm Encryption algorithm 74 | * @returns {string} Randomly generated key 75 | */ 76 | function generateKey(algorithm) { 77 | return handler(algorithm).generateKey(); 78 | } 79 | 80 | /** 81 | * Encrypt the message with the given key. 82 | * @param {string} algorithm Encryption algorithm 83 | * @param {string} key Key to use for encryption 84 | * @param {string} msg String message to encrypt 85 | * @returns {string} Base64-encoded encrypted string 86 | */ 87 | function encrypt(algorithm, key, msg) { 88 | return handler(algorithm).encrypt(key, msg); 89 | } 90 | 91 | /** 92 | * Decrypt the message with the given key. 93 | * @param {string} algorithm Decryption algorithm 94 | * @param {string} key Key to use for decryption 95 | * @param {string} msg Base64 encoded message to decrypt 96 | * @returns {string} Plain text string 97 | */ 98 | function decrypt(algorithm, key, msg) { 99 | if (msg == null) { 100 | throw new Error("message is null!"); 101 | } else if (typeof msg !== "string") { 102 | throw new Error(`invalid type for message: ${typeof msg}`); 103 | } 104 | return handler(algorithm).decrypt(key, msg); 105 | } 106 | 107 | function handler(algorithm) { 108 | if (!algorithm) { 109 | return algorithmHandlers[DEFAULT_ALGORITHM]; 110 | } 111 | let h = algorithmHandlers[algorithm]; 112 | if (h != null) { 113 | return h; 114 | } 115 | for (const a of algorithms) { 116 | if (a.startsWith(`${algorithm}:`)) { 117 | return algorithmHandlers[a]; 118 | } 119 | } 120 | throw new Error(`unknown algorithm: ${algorithm}`); 121 | } 122 | 123 | /** 124 | * Generate a new key that can be used for Fernet cryptography. 125 | * @returns {string} Randomly generated key 126 | */ 127 | function fernetGenerateKey() { 128 | return generateRandomBase64(32); 129 | } 130 | 131 | /** 132 | * Encrypt the message with the given key. 133 | * @param {string} key Key to use for encryption, must be exactly 32 bytes when encoded in UTF-8 134 | * @param {string} msg String message to encrypt 135 | * @returns {string} Base64-encoded encrypted string 136 | */ 137 | function fernetEncrypt(key, msg) { 138 | const secret = new fernet.Secret( 139 | URLSafeBase64.encode(Buffer.from(key, "utf8")) 140 | ); 141 | const token = new fernet.Token({ secret: secret }); 142 | return token.encode(msg); 143 | } 144 | 145 | /** 146 | * Decrypt the message with the given key. 147 | * @param {string} key Key to use for decryption, must be exactly 32 bytes when encoded in UTF-8 148 | * @param {string} msg Base64 encoded message to decrypt 149 | * @returns {string} Plain text string 150 | */ 151 | function fernetDecrypt(key, msg) { 152 | const secret = new fernet.Secret( 153 | URLSafeBase64.encode(Buffer.from(key, "utf8")) 154 | ); 155 | const token = new fernet.Token({ 156 | secret: secret, 157 | token: msg, 158 | // we currently don't impose any TTL on messages: 159 | ttl: 0 160 | }); 161 | return token.decode(); 162 | } 163 | 164 | /** 165 | * Generate a new key that can be used for Branca cryptography. 166 | * @returns {string} Randomly generated key 167 | */ 168 | function brancaGenerateKey() { 169 | return generateRandomBase64(32); 170 | } 171 | 172 | /** 173 | * Encrypt the message with the given key. 174 | * @param {string} key Key to use for encryption, must be exactly 32 bytes when encoded in UTF-8 175 | * @param {string} msg String message to encrypt 176 | * @returns {string} Base62-encoded encrypted string 177 | */ 178 | function brancaEncrypt(key, msg) { 179 | const bytes = Buffer.from(key); 180 | return branca(bytes).encode(msg, __brancaDefaults.ts, __brancaDefaults.nonce); 181 | } 182 | 183 | /** 184 | * Decrypt the message with the given key. 185 | * @param {string} key Key to use for decryption, must be exactly 32 bytes when encoded in UTF-8 186 | * @param {string} msg Base62 encoded message to decrypt 187 | * @returns {string} Plain text string 188 | */ 189 | function brancaDecrypt(key, msg) { 190 | const bytes = Buffer.from(key); 191 | const payload = branca(bytes).decode(msg); 192 | return payload.toString(); 193 | } 194 | 195 | function generateRandomBase64(length) { 196 | const buf = crypto.randomBytes(length); 197 | return buf.toString("base64").substring(0, length); 198 | } 199 | 200 | module.exports = { 201 | __brancaDefaults, 202 | algorithms, 203 | isToken, 204 | generateKey, 205 | encrypt, 206 | decrypt 207 | }; 208 | -------------------------------------------------------------------------------- /test/yaml-crypt-test.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const mocha = require("mocha"); 4 | const describe = mocha.describe; 5 | const it = mocha.it; 6 | const chai = require("chai"); 7 | const expect = chai.expect; 8 | 9 | const tmp = require("tmp"); 10 | const { dump } = require("js-yaml"); 11 | 12 | const { loadFile, loadConfig, yamlcrypt } = require("../lib/yaml-crypt"); 13 | const { setupCrypto, decryptBranca } = require("./crypto-util"); 14 | 15 | setupCrypto(); 16 | 17 | describe("yaml-crypt", () => { 18 | it("should load the config file", async () => { 19 | const config = await loadConfig(); 20 | expect(config).to.not.be.null; 21 | }); 22 | 23 | it("should load the config file from the given path", async () => { 24 | const configFile = tmp.fileSync(); 25 | fs.writeFileSync(configFile.name, "keys:\n - key: 123"); 26 | const config = await loadConfig({ path: configFile.name }); 27 | expect(config).to.not.be.null; 28 | }); 29 | 30 | it("should load the config file from home", async () => { 31 | const home = tmp.dirSync(); 32 | fs.mkdirSync(`${home.name}/.yaml-crypt`); 33 | fs.writeFileSync( 34 | `${home.name}/.yaml-crypt/config.yml`, 35 | "keys:\n - key: 123" 36 | ); 37 | const config = await loadConfig({ home: home.name }); 38 | expect(config).to.not.be.null; 39 | expect(config.keys).to.have.lengthOf(1); 40 | }); 41 | 42 | it("should throw an error when the config file is not readable", async () => { 43 | const home = tmp.dirSync(); 44 | fs.mkdirSync(`${home.name}/.yaml-crypt`); 45 | fs.mkdirSync(`${home.name}/.yaml-crypt/config.yaml`); 46 | try { 47 | await loadConfig({ home: home.name }); 48 | expect.fail("exception expected!"); 49 | } catch (e) { 50 | expect(e.message).to.match(/illegal operation/); 51 | } 52 | }); 53 | 54 | it("should return the default config file", async () => { 55 | const home = tmp.dirSync(); 56 | const config = await loadConfig({ home: home.name }); 57 | expect(config).to.not.be.null; 58 | expect(config.keys).to.be.undefined; 59 | }); 60 | 61 | it("should read the decrypted content via loadFile", async () => { 62 | const config = { keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }; 63 | const result = await loadFile("./test/resources/test-1b.yaml-crypt", { 64 | config 65 | }); 66 | expect(result.key1.toString()).to.equal("Hello, world!"); 67 | expect(result.key2.toString()).to.equal("Hello, world!"); 68 | }); 69 | 70 | it("should read the decrypted content via loadFile (all)", async () => { 71 | const config = { keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }; 72 | const result = await loadFile("./test/resources/test-2.yaml-crypt", { 73 | config, 74 | loadAll: true 75 | }); 76 | expect(result[0].first.toString()).to.equal("Hello, world!"); 77 | expect(result[1].other.toString()).to.equal("Hello, world!"); 78 | }); 79 | 80 | it("should read the decrypted content", () => { 81 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 82 | const content = fs.readFileSync("./test/resources/test-1b.yaml-crypt"); 83 | const result = yaml.decrypt(content); 84 | expect(result.key1.toString()).to.equal("Hello, world!"); 85 | expect(result.key2.toString()).to.equal("Hello, world!"); 86 | }); 87 | 88 | it("should read the decrypted raw content (string)", () => { 89 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 90 | const content = fs.readFileSync("./test/resources/test-7.yaml-crypt"); 91 | const result = yaml.decrypt(content); 92 | expect(result).to.equal("Hello!"); 93 | }); 94 | 95 | it("should read the decrypted raw content (Buffer)", () => { 96 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 97 | const content = fs.readFileSync("./test/resources/test-7.yaml-crypt"); 98 | const result = yaml.decryptAll(content.toString()); 99 | expect(result[0]).to.equal("Hello!"); 100 | }); 101 | 102 | it("should return the encrypted content", () => { 103 | const yaml = yamlcrypt({ 104 | encryptionKey: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" 105 | }); 106 | const str = '{ key1: "Hello, world!", key2: "Hello, world!" }'; 107 | const result = yaml.encrypt(str); 108 | const expected = fs 109 | .readFileSync("./test/resources/test-1a.yaml-crypt") 110 | .toString("utf8"); 111 | expect(result).to.equal(expected); 112 | }); 113 | 114 | it("should return the encrypted raw content", () => { 115 | const key = "aehae5Ui0Eechaeghau9Yoh9jufiep7H"; 116 | const yaml = yamlcrypt({ encryptionKey: key }); 117 | const str = "Hello!"; 118 | const result1 = yaml.encrypt(str, { algorithm: "branca", raw: true }); 119 | const result2 = yaml.encryptAll(str, { algorithm: "branca", raw: true }); 120 | expect(decryptBranca(key, result1)).to.equal(str); 121 | expect(decryptBranca(key, result2)).to.equal(str); 122 | }); 123 | 124 | it("should return the base64 encrypted content", () => { 125 | const yaml = yamlcrypt({ 126 | encryptionKey: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" 127 | }); 128 | const result = yaml.encryptAll("base64: Hello, world!", { base64: true }); 129 | const expected = fs 130 | .readFileSync("./test/resources/test-4.yaml-crypt") 131 | .toString("utf8"); 132 | expect(result).to.equal(expected); 133 | }); 134 | 135 | it("should read the decrypted base64 content", () => { 136 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 137 | const content = fs.readFileSync("./test/resources/test-4.yaml-crypt"); 138 | const result = yaml.decryptAll(content, { base64: true })[0]; 139 | expect(result.base64.toString()).to.equal("Hello, world!"); 140 | }); 141 | 142 | it("should correctly transform the nested content", () => { 143 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 144 | const content = fs.readFileSync("./test/resources/test-5.yaml-crypt"); 145 | let decrypted = null; 146 | yaml.transform(content, str => (decrypted = str)); 147 | expect(decrypted).to.contain("str: ! Hello!"); 148 | }); 149 | 150 | it("should re-encrypt transformed content", () => { 151 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 152 | const content1 = fs.readFileSync("./test/resources/test-6.yaml-crypt"); 153 | const transformed = yaml.transform(content1, str => 154 | str.replace("Hello!", "Hello, world!") 155 | ); 156 | expect(transformed).to.not.equal(content1.toString()); 157 | }); 158 | 159 | it("should encrypt new content when transforming", () => { 160 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 161 | const expected = fs.readFileSync("./test/resources/test-1a.yaml-crypt"); 162 | const newContent = 163 | "key1: ! Hello, world!\nkey2: ! Hello, world!"; 164 | const transformed = yaml.transform("", () => newContent); 165 | expect(transformed).to.equal(expected.toString()); 166 | }); 167 | 168 | it("should not re-encrypt unchanged content when transforming", () => { 169 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 170 | const content = fs.readFileSync("./test/resources/test-7.yaml-crypt"); 171 | const transformed = yaml.transform(content, str => str); 172 | expect(transformed).to.equal(content); 173 | }); 174 | 175 | it("should re-encrypt transformed raw content", () => { 176 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 177 | const content = fs.readFileSync("./test/resources/test-7.yaml-crypt"); 178 | const transformed = yaml.transform(content, str => 179 | str.replace("Hello!", "Hello, world!") 180 | ); 181 | expect(transformed).to.not.equal(content); 182 | }); 183 | 184 | it("should correctly parse primitive types", () => { 185 | const yaml = yamlcrypt({ keys: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }); 186 | const content = fs.readFileSync("./test/resources/test-8.yaml", "utf8"); 187 | const transformed = dump(yaml.decrypt(content)); 188 | expect(transformed).to.equal(content); 189 | }); 190 | 191 | it("should throw an error when an invalid key is given", () => { 192 | expect(() => yamlcrypt({ keys: 0 })).to.throw( 193 | "invalid key unknown source: number" 194 | ); 195 | }); 196 | 197 | it("should throw an error when an empty key is given", () => { 198 | expect(() => 199 | yamlcrypt({ keys: { source: "config:test", key: "" } }) 200 | ).to.throw("empty key: config:test"); 201 | }); 202 | }); 203 | -------------------------------------------------------------------------------- /lib/yaml-crypt.js: -------------------------------------------------------------------------------- 1 | const { homedir } = require("os"); 2 | const { readFile } = require("fs"); 3 | const { join } = require("path"); 4 | 5 | const yaml = require("js-yaml"); 6 | 7 | const { 8 | algorithms, 9 | isToken, 10 | generateKey, 11 | encrypt, 12 | decrypt 13 | } = require("./crypto"); 14 | const { 15 | dump, 16 | dumpAll, 17 | loadAll, 18 | walkStringValues, 19 | walkValues, 20 | tryDecrypt 21 | } = require("./utils"); 22 | 23 | async function loadFile(path, { config, loadAll } = { loadAll: false }) { 24 | const cfg = config ? config : await loadConfig(); 25 | const content = await readFileAsync(path); 26 | const yc = yamlcrypt(cfg); 27 | return loadAll ? yc.decryptAll(content) : yc.decrypt(content); 28 | } 29 | 30 | async function loadConfig({ home, path } = {}) { 31 | let content = null; 32 | if (path) { 33 | content = await readFileAsync(path); 34 | } else { 35 | let h = home ? home : homedir(); 36 | for (const filename of ["config.yaml", "config.yml"]) { 37 | try { 38 | content = await readFileAsync(join(h, ".yaml-crypt", filename)); 39 | break; 40 | } catch (e) { 41 | if (e.code === "ENOENT") { 42 | continue; 43 | } else { 44 | throw e; 45 | } 46 | } 47 | } 48 | } 49 | if (content) { 50 | return yaml.load(content); 51 | } else { 52 | // default config 53 | return {}; 54 | } 55 | } 56 | 57 | function readFileAsync(path) { 58 | return new Promise((resolve, reject) => { 59 | readFile(path, (err, data) => { 60 | if (err) { 61 | reject(err); 62 | } else { 63 | resolve(data); 64 | } 65 | }); 66 | }); 67 | } 68 | 69 | function yamlcrypt({ keys, encryptionKey } = {}) { 70 | const normalizedKeys = normalizeKeys(keys); 71 | const normalizedEncryptionKey = normalizeKey(encryptionKey); 72 | return createYamlcrypt( 73 | normalizedKeys, 74 | normalizedEncryptionKey == null 75 | ? normalizedKeys.length === 1 76 | ? normalizedKeys[0] 77 | : null 78 | : normalizedEncryptionKey 79 | ); 80 | } 81 | 82 | function normalizeKey(key) { 83 | const k = key && key.key !== undefined ? key : { key }; 84 | if (k == null || k.key == null) { 85 | return null; 86 | } 87 | 88 | if (!k.source) { 89 | k.source = "unknown source"; 90 | } 91 | 92 | if (typeof k.key !== "string") { 93 | throw new Error(`invalid key ${k.source}: ${typeof k.key}`); 94 | } else if (k.key.length === 0) { 95 | throw new Error(`empty key: ${k.source}`); 96 | } else { 97 | return k; 98 | } 99 | } 100 | 101 | function normalizeKeys(keys) { 102 | const arr = Array.isArray(keys) 103 | ? keys.map(normalizeKey) 104 | : [normalizeKey(keys)]; 105 | return arr.filter(key => key != null); 106 | } 107 | 108 | function createYamlcrypt(keys, encryptionKey) { 109 | function mergeOpts(opts) { 110 | const result = Object.assign({}, opts); 111 | if (!Object.prototype.hasOwnProperty.call(result, "keys")) { 112 | result.keys = keys; 113 | } 114 | if (!Object.prototype.hasOwnProperty.call(result, "encryptionKey")) { 115 | result.encryptionKey = encryptionKey; 116 | } 117 | return result; 118 | } 119 | 120 | function trimStr(buf) { 121 | if (Buffer.isBuffer(buf)) { 122 | return buf.toString("ascii").trimRight(); 123 | } else { 124 | return buf.trimRight(); 125 | } 126 | } 127 | 128 | return { 129 | encrypt: (str, opts = {}) => { 130 | if (opts.raw) { 131 | return encrypt( 132 | opts.algorithm, 133 | (opts.encryptionKey || encryptionKey).key, 134 | str 135 | ); 136 | } else { 137 | const obj = yaml.load(str); 138 | walkStringValues(obj, opts.path, s => new Plaintext(s)); 139 | return dump(obj, yamlOpts(mergeOpts(opts))); 140 | } 141 | }, 142 | 143 | encryptAll: (str, opts = {}) => { 144 | if (opts.raw) { 145 | return encrypt( 146 | opts.algorithm, 147 | (opts.encryptionKey || encryptionKey).key, 148 | str 149 | ); 150 | } else { 151 | const objs = yaml.loadAll(str); 152 | for (const obj of objs) { 153 | walkStringValues(obj, opts.path, s => new Plaintext(s)); 154 | } 155 | return dumpAll(objs, yamlOpts(mergeOpts(opts))); 156 | } 157 | }, 158 | 159 | decrypt: (str, opts = {}) => { 160 | if (opts.raw || isToken(str)) { 161 | const s = trimStr(str); 162 | const { decrypted } = tryDecrypt( 163 | algorithms, 164 | opts.keys || keys, 165 | (algorithm, key) => decrypt(algorithm, key.key, s) 166 | ); 167 | return yaml.load(decrypted); 168 | } else { 169 | return yaml.load(str, yamlOpts(mergeOpts(opts))); 170 | } 171 | }, 172 | 173 | decryptAll: (str, opts = {}) => { 174 | if (opts.raw || isToken(str)) { 175 | const s = trimStr(str); 176 | const { decrypted, key } = tryDecrypt( 177 | algorithms, 178 | opts.keys || keys, 179 | (algorithm, key) => decrypt(algorithm, key.key, s) 180 | ); 181 | if (opts.callback) { 182 | opts.callback(key); 183 | } 184 | return loadAll(decrypted); 185 | } else { 186 | return loadAll(str, yamlOpts(mergeOpts(opts))); 187 | } 188 | }, 189 | 190 | transform: (str, callback, opts = {}) => { 191 | if (opts.raw || isToken(str)) { 192 | const s = trimStr(str); 193 | const { key, algorithm, decrypted } = tryDecrypt( 194 | algorithms, 195 | opts.keys || keys, 196 | (algorithm, key) => decrypt(algorithm, key.key, s) 197 | ); 198 | 199 | const transformed = callback(decrypted, key); 200 | 201 | if (transformed.toString() === decrypted) { 202 | return str; 203 | } else { 204 | return encrypt(algorithm, key.key, transformed); 205 | } 206 | } else { 207 | return doTransform(str, callback, mergeOpts(opts)); 208 | } 209 | } 210 | }; 211 | } 212 | 213 | function yamlOpts(opts) { 214 | const schema = createYamlSchema({ 215 | keys: opts.keys, 216 | encryptionKey: opts.encryptionKey, 217 | algorithm: opts.algorithm, 218 | objects: !!opts.objects, 219 | base64: !!opts.base64, 220 | callback: opts.callback 221 | }); 222 | return { schema }; 223 | } 224 | 225 | function createYamlSchema({ 226 | algorithm, 227 | keys, 228 | encryptionKey, 229 | objects, 230 | base64, 231 | callback 232 | }) { 233 | const opts = { keys, encryptionKey, objects, base64, callback }; 234 | const types = []; 235 | for (let i = 0; i < algorithms.length; i++) { 236 | const isDefault = 237 | algorithms[i] === algorithm || (algorithm == null && i === 0); 238 | types.push( 239 | createType( 240 | Object.assign({}, opts, { 241 | algorithm: algorithms[i], 242 | isDefault 243 | }) 244 | ) 245 | ); 246 | } 247 | return yaml.DEFAULT_SCHEMA.extend(types); 248 | } 249 | 250 | function createType({ 251 | algorithm, 252 | isDefault, 253 | keys, 254 | encryptionKey, 255 | objects, 256 | base64, 257 | callback 258 | }) { 259 | const name = "!yaml-crypt" + (algorithm == null ? "" : `/${algorithm}`); 260 | const type = new yaml.Type(name, { 261 | kind: "scalar", 262 | instanceOf: Plaintext, 263 | resolve: data => data !== null, 264 | construct: data => { 265 | const { decrypted, key } = tryDecrypt( 266 | [algorithm], 267 | keys, 268 | (algorithm, key) => decrypt(algorithm, key.key, data) 269 | ); 270 | if (callback) { 271 | callback(key); 272 | } 273 | const decoded = base64 274 | ? Buffer.from(decrypted, "base64").toString("utf8") 275 | : decrypted; 276 | return objects ? new Plaintext(decoded, data, algorithm) : decoded; 277 | }, 278 | predicate: data => { 279 | return ( 280 | data.algorithm === algorithm || (data.algorithm == null && isDefault) 281 | ); 282 | }, 283 | represent: data => { 284 | let encrypted; 285 | if (data.ciphertext) { 286 | encrypted = data.ciphertext; 287 | } else { 288 | const str = data.toString(); 289 | const encoded = base64 ? Buffer.from(str).toString("base64") : str; 290 | encrypted = encrypt(algorithm, encryptionKey.key, encoded); 291 | } 292 | return encrypted; 293 | } 294 | }); 295 | return type; 296 | } 297 | 298 | function doTransform(str, callback, opts) { 299 | const { key, decrypted: docs } = tryDecrypt( 300 | algorithms, 301 | opts.keys, 302 | (algorithm, key) => { 303 | const o = Object.assign({}, opts); 304 | o.objects = true; 305 | o.algorithm = algorithm; 306 | o.keys = [key]; 307 | return loadAll(str, yamlOpts(o)); 308 | } 309 | ); 310 | 311 | if (!opts.encryptionKey) { 312 | opts.encryptionKey = key; 313 | } 314 | 315 | const reencrypting = key !== opts.encryptionKey; 316 | 317 | let index = 0; 318 | const types = []; 319 | for (const doc of docs) { 320 | walkValues( 321 | doc, 322 | null, 323 | v => v instanceof Plaintext, 324 | t => { 325 | const knownText = new KnownText(t.algorithm, t, index++); 326 | types.push(knownTextType(knownText, reencrypting)); 327 | return knownText; 328 | } 329 | ); 330 | } 331 | 332 | newTextTypes().forEach(t => types.push(t)); 333 | 334 | const schema = yaml.DEFAULT_SCHEMA.extend(types); 335 | const decrypted = dumpAll(docs, { schema: schema }); 336 | 337 | const transformed = callback(decrypted, key); 338 | 339 | const result = loadAll(transformed, { schema: schema }); 340 | return dumpAll(result, yamlOpts(opts)); 341 | } 342 | 343 | function knownTextType(knownText, reencrypt) { 344 | return new yaml.Type(`!yaml-crypt/:${knownText.index}`, { 345 | kind: "scalar", 346 | instanceOf: KnownText, 347 | predicate: data => data.index === knownText.index, 348 | represent: data => data.plaintext.plaintext, 349 | construct: data => { 350 | if (reencrypt || data !== knownText.plaintext.plaintext) { 351 | return new Plaintext(data, null, knownText.algorithm); 352 | } else { 353 | return knownText.plaintext; 354 | } 355 | } 356 | }); 357 | } 358 | 359 | function newTextTypes() { 360 | const keys = [{ type: "!yaml-crypt", algorithm: algorithms[0] }]; 361 | for (const algorithm of algorithms) { 362 | // also allow the usage of just the algorithm name, without version: 363 | const split = algorithm.split(":", 2); 364 | keys.push({ type: `!yaml-crypt/${split[0]}`, algorithm: algorithm }); 365 | keys.push({ type: `!yaml-crypt/${algorithm}`, algorithm: algorithm }); 366 | } 367 | return keys.map( 368 | key => 369 | new yaml.Type(key.type, { 370 | kind: "scalar", 371 | construct: data => new Plaintext(data, null, key.algorithm) 372 | }) 373 | ); 374 | } 375 | 376 | class Plaintext { 377 | constructor(plaintext, ciphertext = null, algorithm = null) { 378 | this.plaintext = plaintext; 379 | this.ciphertext = ciphertext; 380 | this.algorithm = algorithm; 381 | } 382 | 383 | toString() { 384 | return this.plaintext; 385 | } 386 | } 387 | 388 | class KnownText { 389 | constructor(algorithm, plaintext, index) { 390 | this.algorithm = algorithm; 391 | this.plaintext = plaintext; 392 | this.index = index; 393 | } 394 | } 395 | 396 | module.exports = { 397 | algorithms, 398 | generateKey, 399 | loadFile, 400 | loadConfig, 401 | yamlcrypt, 402 | encrypt, 403 | decrypt 404 | }; 405 | -------------------------------------------------------------------------------- /test/yaml-crypt-cli-test.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const mocha = require("mocha"); 4 | const describe = mocha.describe; 5 | const it = mocha.it; 6 | const chai = require("chai"); 7 | const expect = chai.expect; 8 | 9 | const tmp = require("tmp"); 10 | 11 | const { dump } = require("../lib/utils"); 12 | const yamlcryptcli = require("../bin/yaml-crypt-cli"); 13 | 14 | require("./crypto-util").setupCrypto(); 15 | 16 | class Out { 17 | constructor() { 18 | this.str = ""; 19 | } 20 | 21 | write(obj) { 22 | if (typeof obj === "string") { 23 | this.str += obj; 24 | } else { 25 | this.str += obj.toString(); 26 | } 27 | } 28 | } 29 | 30 | describe("yaml-crypt-cli", () => { 31 | it("should display a message about details when giving -h", () => { 32 | const stdout = new Out(); 33 | try { 34 | yamlcryptcli.run(["-h"], {}, { stdout }); 35 | } catch (e) { 36 | // ignore 37 | } 38 | expect(stdout.str).to.contain("For more details, specify --help"); 39 | }); 40 | 41 | it("should throw an error when using --unknown-option", () => { 42 | expect(() => 43 | yamlcryptcli.run(["--unknown-option"], {}, { stdout: new Out() }) 44 | ) 45 | .to.throw() 46 | .with.property("status", 2); 47 | }); 48 | 49 | it("should display usage info when using --help", () => { 50 | expect(() => yamlcryptcli.run(["--help"], {}, { stdout: new Out() })) 51 | .to.throw() 52 | .with.property("status", 0); 53 | }); 54 | 55 | it("should throw an error when combining invalid flags", () => { 56 | const invalid = [ 57 | ["--raw", "--path", "."], 58 | ["--raw", "--query", "."], 59 | ["--edit", "--query", "."], 60 | ["--edit", "--encrypt"], 61 | ["--edit", "--decrypt"], 62 | ["--edit", "--keep"], 63 | ["--generate-key", "-e"], 64 | ["--generate-key", "-d"] 65 | ]; 66 | for (const args of invalid) { 67 | expect(() => runWithKeyFile(args, {}, {})).to.throw(/cannot combine/); 68 | } 69 | }); 70 | 71 | it("should throw an error when passing directory without --dir", () => { 72 | expect(() => runWithKeyFile(["."], {}, { stdout: new Out() })).to.throw( 73 | /directories will be skipped/ 74 | ); 75 | }); 76 | 77 | it("should throw an error when passing non-existing files to --edit", () => { 78 | expect(() => 79 | runWithKeyFile(["--edit", "x.yaml-crypt"], {}, { stdout: new Out() }) 80 | ).to.throw(/file does not exist/); 81 | }); 82 | 83 | it("should throw an error when passing query without decrypt", () => { 84 | expect(() => runWithKeyFile(["--query", "."], {}, {})).to.throw( 85 | /must be combined with/ 86 | ); 87 | }); 88 | 89 | it("should throw an error when passing query with files", () => { 90 | expect(() => runWithKeyFile(["--query", ".", "x"], {}, {})).to.throw( 91 | /only valid when reading from stdin/ 92 | ); 93 | }); 94 | 95 | it("should throw an error when passing invalid algorithm", () => { 96 | expect(() => runWithKeyFile(["-d", "-a", "x"], {}, {})).to.throw( 97 | /unknown encryption algorithm/ 98 | ); 99 | }); 100 | 101 | it("should throw an error when encrypting with two keys", () => { 102 | const secondKeyFile = tmp.fileSync(); 103 | fs.writeSync(secondKeyFile.fd, "aehae5Ui0Eechaeghau9Yoh9jufiep72"); 104 | expect(() => 105 | runWithKeyFile( 106 | ["-k", secondKeyFile.name, "-e"], 107 | {}, 108 | { stdout: new Out() } 109 | ) 110 | ).to.throw(/encrypting, but multiple keys given/); 111 | }); 112 | 113 | it("should throw an error when trying to read a nonexisting environment variable", () => { 114 | expect(() => 115 | yamlcryptcli.run(["-k", "env:YAML_CRYPT_321"], {}, { stdout: new Out() }) 116 | ).to.throw(/no such environment variable/); 117 | }); 118 | 119 | it("should throw an error when passing an invalid file descriptor", () => { 120 | expect(() => 121 | yamlcryptcli.run(["-k", "fd:x"], {}, { stdout: new Out() }) 122 | ).to.throw(/not a file descriptor/); 123 | }); 124 | 125 | it("should generate a key", () => { 126 | const options = { 127 | stdin: "", 128 | stdout: new Out() 129 | }; 130 | yamlcryptcli.run(["--generate-key"], {}, options); 131 | expect(options.stdout.str.trimRight()).to.have.lengthOf(32); 132 | }); 133 | 134 | it("should encrypt the given YAML file (fernet)", () => { 135 | const input = tmp.fileSync({ postfix: ".yaml" }); 136 | fs.copyFileSync("./test/resources/test-2.yaml", input.name); 137 | runWithKeyFile([input.name], {}, { stdout: new Out() }); 138 | const output = fs.readFileSync(input.name + "-crypt"); 139 | const expected = fs.readFileSync("./test/resources/test-2.yaml-crypt"); 140 | expect(output.toString("utf8")).to.equal(expected.toString("utf8")); 141 | }); 142 | 143 | it("should encrypt the given YAML file (branca)", () => { 144 | const input = tmp.fileSync({ postfix: ".yaml" }); 145 | fs.copyFileSync("./test/resources/test-2.yaml", input.name); 146 | runWithKeyFile(["-a", "branca", input.name], {}, { stdout: new Out() }); 147 | const output = fs.readFileSync(input.name + "-crypt"); 148 | expect(output.toString("utf8")).to.not.be.empty; 149 | }); 150 | 151 | it("should decrypt the given YAML file", () => { 152 | const input = tmp.fileSync({ postfix: ".yaml-crypt" }); 153 | fs.copyFileSync("./test/resources/test-2.yaml-crypt", input.name); 154 | runWithKeyFile([input.name], {}, { stdout: new Out() }); 155 | const output = fs.readFileSync( 156 | input.name.substring(0, input.name.length - "-crypt".length) 157 | ); 158 | const expected = fs.readFileSync("./test/resources/test-2.yaml"); 159 | expect(output.toString("utf8")).to.equal(expected.toString("utf8")); 160 | }); 161 | 162 | it("should throw an error when the output file exists", () => { 163 | const tmpdir = tmp.dirSync(); 164 | fs.copyFileSync( 165 | "./test/resources/test-2.yaml-crypt", 166 | `${tmpdir.name}/2.yaml-crypt` 167 | ); 168 | fs.copyFileSync("./test/resources/test-2.yaml", `${tmpdir.name}/2.yaml`); 169 | expect(() => 170 | runWithKeyFile( 171 | ["-d", `${tmpdir.name}/2.yaml-crypt`], 172 | {}, 173 | { stdout: new Out() } 174 | ) 175 | ).to.throw(/output file already exists/); 176 | }); 177 | 178 | it("should succeed when the output file exists and -f is given", () => { 179 | const tmpdir = tmp.dirSync(); 180 | fs.copyFileSync( 181 | "./test/resources/test-2.yaml-crypt", 182 | `${tmpdir.name}/2.yaml-crypt` 183 | ); 184 | fs.copyFileSync("./test/resources/test-2.yaml", `${tmpdir.name}/2.yaml`); 185 | runWithKeyFile( 186 | ["-d", "--force", `${tmpdir.name}/2.yaml-crypt`], 187 | {}, 188 | { stdout: new Out() } 189 | ); 190 | }); 191 | 192 | it("should decrypt the given directory", () => { 193 | const tmpdir = tmp.dirSync(); 194 | fs.copyFileSync( 195 | "./test/resources/test-2.yaml-crypt", 196 | `${tmpdir.name}/1.yaml-crypt` 197 | ); 198 | fs.copyFileSync( 199 | "./test/resources/test-2.yaml-crypt", 200 | `${tmpdir.name}/2.yml-crypt` 201 | ); 202 | runWithKeyFile(["--dir", tmpdir.name], {}, { stdout: new Out() }); 203 | const expected = fs.readFileSync("./test/resources/test-2.yaml"); 204 | const output1 = fs.readFileSync(`${tmpdir.name}/1.yaml`); 205 | const output2 = fs.readFileSync(`${tmpdir.name}/2.yml`); 206 | expect(output1.toString("utf8")).to.equal(expected.toString("utf8")); 207 | expect(output2.toString("utf8")).to.equal(expected.toString("utf8")); 208 | }); 209 | 210 | it("should encrypt only parts of the YAML file when using --path", () => { 211 | const input = tmp.fileSync({ postfix: ".yaml" }); 212 | fs.writeSync(input.fd, dump({ a: { b: { c: "secret" } }, x: "plain" })); 213 | runWithKeyFile(["--path", "a.b.c", input.name], {}, { stdout: new Out() }); 214 | const output = fs.readFileSync(input.name + "-crypt"); 215 | const expected = fs.readFileSync("./test/resources/test-3.yaml-crypt"); 216 | expect(output.toString("utf8")).to.equal(expected.toString("utf8")); 217 | }); 218 | 219 | it("should remove the old files", () => { 220 | const input = tmp.fileSync({ postfix: ".yaml" }); 221 | fs.copyFileSync("./test/resources/test-2.yaml", input.name); 222 | runWithKeyFile([input.name], {}, { stdout: new Out() }); 223 | expect(fs.existsSync(input.name)).to.equal(false); 224 | }); 225 | 226 | it("should not remove the old files when using --keep", () => { 227 | const input = tmp.fileSync({ postfix: ".yaml" }); 228 | fs.copyFileSync("./test/resources/test-2.yaml", input.name); 229 | runWithKeyFile(["--keep", input.name], {}, { stdout: new Out() }); 230 | expect(fs.existsSync(input.name)).to.equal(true); 231 | }); 232 | 233 | function runWithKeyFile(argv, config, options) { 234 | const keyFile = tmp.fileSync(); 235 | fs.writeSync(keyFile.fd, "aehae5Ui0Eechaeghau9Yoh9jufiep7H"); 236 | return yamlcryptcli.run(["-k", keyFile.name].concat(argv), config, options); 237 | } 238 | 239 | it("should decrypt the given YAML file (key passed via fd)", () => { 240 | const input = tmp.fileSync({ postfix: ".yaml-crypt" }); 241 | fs.copyFileSync("./test/resources/test-2.yaml-crypt", input.name); 242 | const keyFile = tmp.fileSync(); 243 | fs.writeFileSync(keyFile.name, "aehae5Ui0Eechaeghau9Yoh9jufiep7H"); 244 | const fd = fs.openSync(keyFile.name, "r"); 245 | yamlcryptcli.run(["-k", `fd:${fd}`, input.name], {}, { stdout: new Out() }); 246 | const output = fs.readFileSync( 247 | input.name.substring(0, input.name.length - "-crypt".length) 248 | ); 249 | const expected = fs.readFileSync("./test/resources/test-2.yaml"); 250 | expect(output.toString("utf8")).to.equal(expected.toString("utf8")); 251 | }); 252 | 253 | it("should throw an error when no matching key is available", () => { 254 | const keyFile = tmp.fileSync(); 255 | fs.writeSync(keyFile.fd, "INVALID_KEYchaeghau9Yoh9jufiep7H"); 256 | const input = tmp.fileSync({ postfix: ".yaml-crypt" }); 257 | fs.copyFileSync("./test/resources/test-2.yaml-crypt", input.name); 258 | expect(() => 259 | yamlcryptcli.run( 260 | ["-k", keyFile.name, input.name], 261 | {}, 262 | { stdout: new Out() } 263 | ) 264 | ).to.throw(/no matching key/); 265 | }); 266 | 267 | it("should not throw an error when --continue is given", () => { 268 | const keyFile = tmp.fileSync(); 269 | fs.writeSync(keyFile.fd, "INVALID_KEYchaeghau9Yoh9jufiep7H"); 270 | const input = tmp.fileSync({ postfix: ".yaml-crypt" }); 271 | fs.copyFileSync("./test/resources/test-2.yaml-crypt", input.name); 272 | yamlcryptcli.run( 273 | ["--continue", "-k", keyFile.name, input.name], 274 | {}, 275 | { stderr: new Out() } 276 | ); 277 | }); 278 | 279 | it("should throw an error when no named key is available in the config file", () => { 280 | const config = { 281 | keys: [] 282 | }; 283 | const options = { 284 | stdin: "", 285 | stdout: new Out() 286 | }; 287 | expect(() => 288 | yamlcryptcli.run(["-k", "config:name1", "-d"], config, options) 289 | ).to.throw(/key not found in configuration file/); 290 | }); 291 | 292 | it("should throw an error when the key names are not unique in the config file", () => { 293 | const config = { 294 | keys: [ 295 | { key: "a", name: "key1" }, 296 | { key: "b", name: "key1" } 297 | ] 298 | }; 299 | const options = { 300 | stdin: "", 301 | stdout: new Out() 302 | }; 303 | expect(() => yamlcryptcli.run(["-d"], config, options)).to.throw( 304 | /non-unique key name/ 305 | ); 306 | }); 307 | 308 | it("should decrypt the given input", () => { 309 | const config = { 310 | keys: [ 311 | { key: "INVALID_KEY____________________X" }, 312 | { key: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" } 313 | ] 314 | }; 315 | const options = { 316 | stdin: fs.readFileSync("./test/resources/test-2.yaml-crypt"), 317 | stdout: new Out() 318 | }; 319 | yamlcryptcli.run(["-d"], config, options); 320 | const expected = fs.readFileSync("./test/resources/test-2.yaml").toString(); 321 | expect(options.stdout.str).to.equal(expected); 322 | }); 323 | 324 | it("should decrypt the given input and return the query string", () => { 325 | const config = { keys: [{ key: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }] }; 326 | const options = { 327 | stdin: fs.readFileSync("./test/resources/test-2.yaml-crypt"), 328 | stdout: new Out() 329 | }; 330 | yamlcryptcli.run(["-d", "--query", "first"], config, options); 331 | expect(options.stdout.str).to.equal("Hello, world!\n\n"); 332 | }); 333 | 334 | it("should decrypt the given input and return the query object", () => { 335 | const config = { keys: [{ key: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }] }; 336 | const options = { 337 | stdin: fs.readFileSync("./test/resources/test-3.yaml-crypt"), 338 | stdout: new Out() 339 | }; 340 | yamlcryptcli.run(["-d", "--query", "a"], config, options); 341 | expect(options.stdout.str).to.equal('{"b":{"c":"secret"}}\n'); 342 | }); 343 | 344 | it("should decrypt the given input when using --raw", () => { 345 | const config = { 346 | keys: [ 347 | { key: "INVALID_KEY_123________________X" }, 348 | { key: "aehae5Ui0Eechaeghau9Yoh9jufiep7H" }, 349 | { key: "INVALID_KEY_345________________X" } 350 | ] 351 | }; 352 | const input = 353 | "gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg=="; 354 | const options = { 355 | stdin: Buffer.from(input), 356 | stdout: new Out() 357 | }; 358 | yamlcryptcli.run(["-d", "--raw"], config, options); 359 | expect(options.stdout.str).to.equal("Hello, world!"); 360 | }); 361 | 362 | it("should encrypt the whole input when using --raw", () => { 363 | const config = { 364 | keys: [ 365 | { key: "KEY_THAT_SHOULD_NOT_BE_USED_____", name: "key1" }, 366 | { key: "aehae5Ui0Eechaeghau9Yoh9jufiep7H", name: "key2" } 367 | ] 368 | }; 369 | const options = { 370 | stdin: "Hello, world!", 371 | stdout: new Out() 372 | }; 373 | yamlcryptcli.run(["-e", "--raw", "-K", "c:key2"], config, options); 374 | const expected = 375 | "gAAAAAAAAAABAAECAwQFBgcICQoLDA0OD7nQ_JQsjDx78n7mQ9bW3T-rgiTN7WX3Uq66EDA0qxZDNQppXL6WaOAIW4x8ElmcRg==\n"; 376 | expect(options.stdout.str).to.equal(expected); 377 | }); 378 | 379 | it("should return the same YAML file when using --edit and not changing anything", () => { 380 | const keyFile = tmp.fileSync(); 381 | fs.writeSync(keyFile.fd, "aehae5Ui0Eechaeghau9Yoh9jufiep7H"); 382 | 383 | const input = tmp.fileSync({ 384 | postfix: ".yaml-crypt", 385 | discardDescriptor: true 386 | }); 387 | fs.copyFileSync("./test/resources/test-2.yaml-crypt", input.name); 388 | 389 | yamlcryptcli.run( 390 | ["-k", keyFile.name, "--edit", input.name], 391 | { editor: "touch" }, 392 | {} 393 | ); 394 | 395 | const output = fs.readFileSync(input.name); 396 | const expected = fs.readFileSync("./test/resources/test-2.yaml-crypt"); 397 | expect(output.toString("utf8")).to.equal(expected.toString("utf8")); 398 | }); 399 | }); 400 | -------------------------------------------------------------------------------- /bin/yaml-crypt-cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* eslint-disable no-console */ 4 | 5 | const fs = require("fs"); 6 | const { homedir } = require("os"); 7 | const path = require("path"); 8 | const process = require("process"); 9 | const childProcess = require("child_process"); 10 | 11 | const tmp = require("tmp"); 12 | const argparse = require("argparse"); 13 | 14 | const { 15 | algorithms, 16 | loadConfig, 17 | generateKey, 18 | yamlcrypt, 19 | encrypt, 20 | decrypt 21 | } = require("../lib/yaml-crypt"); 22 | const { UsageError, dumpAll, tryDecrypt, walkValues } = require("../lib/utils"); 23 | const { walk } = require("../lib/yaml-crypt-helper"); 24 | 25 | require("pkginfo")(module); 26 | 27 | async function main() { 28 | let cfg; 29 | try { 30 | cfg = await loadConfig(); 31 | } catch (e) { 32 | console.warn("could not read config file, using default!"); 33 | if (e.message) { 34 | console.warn(`error: ${e.message}`); 35 | } 36 | cfg = {}; 37 | } 38 | try { 39 | run(undefined, cfg, {}); 40 | } catch (e) { 41 | handleError(e); 42 | } 43 | } 44 | 45 | function handleError(e) { 46 | if (e instanceof ExitError) { 47 | process.exitCode = e.status; 48 | } else if (e instanceof UsageError || e instanceof UnknownError) { 49 | console.error(`${module.exports.name}: error: ${e.message}`); 50 | process.exitCode = 5; 51 | } else if (e instanceof ConfigurationError) { 52 | console.error( 53 | `${module.exports.name}: could not parse configuration: ${e.message}` 54 | ); 55 | process.exitCode = 6; 56 | } else { 57 | throw e; 58 | } 59 | } 60 | 61 | function run(argv, config = {}, options = {}) { 62 | class Parser extends argparse.ArgumentParser { 63 | exit(status, message) { 64 | if (message) { 65 | if (status === 0) { 66 | this._print_message(message); 67 | } else { 68 | this._print_message(message, process.stderr); 69 | } 70 | } 71 | throw new ExitError(status || 0); 72 | } 73 | 74 | error(err) { 75 | if (err instanceof ExitError) { 76 | throw err; 77 | } else { 78 | super.error(err); 79 | } 80 | } 81 | 82 | _print_message(message, stream) { 83 | if (message) { 84 | if (options.stdout) { 85 | stream = options.stdout; 86 | } else if (!stream) { 87 | stream = process.stdout; 88 | } 89 | stream.write("" + message); 90 | } 91 | } 92 | } 93 | const parser = new Parser({ 94 | prog: module.exports.name, 95 | add_help: true, 96 | description: module.exports.description 97 | }); 98 | parser.add_argument("-v", "--version", { 99 | action: "version", 100 | version: module.exports.version, 101 | help: "Show version number and exit" 102 | }); 103 | parser.add_argument("--debug", { 104 | action: "store_true", 105 | help: "Show debugging output" 106 | }); 107 | parser.add_argument("-e", "--encrypt", { 108 | action: "store_true", 109 | help: "Encrypt data" 110 | }); 111 | parser.add_argument("-d", "--decrypt", { 112 | action: "store_true", 113 | help: "Decrypt data" 114 | }); 115 | parser.add_argument("--generate-key", { 116 | action: "store_true", 117 | help: "Generate a new random key. Use -a to specify the algorithm" 118 | }); 119 | parser.add_argument("--write-key", { 120 | metavar: "", 121 | help: "Read a key from stdin and write it to the configuration file under the given name" 122 | }); 123 | parser.add_argument("-k", { 124 | action: "append", 125 | metavar: "", 126 | help: 'Use the given key to decrypt data. Can be given multiple times. See section "Key sources" for details' 127 | }); 128 | parser.add_argument("-K", { 129 | metavar: "", 130 | help: 'Use the given key to encrypt data. See section "Key sources" for details' 131 | }); 132 | parser.add_argument("-a", "--algorithm", { 133 | metavar: "", 134 | help: 'The encryption algorithm to use. Must be one of "fernet" (default) or "branca"' 135 | }); 136 | parser.add_argument("-E", "--edit", { 137 | action: "store_true", 138 | help: "Open an editor for the given files, transparently decrypting and encrypting the file content" 139 | }); 140 | parser.add_argument("-B", "--base64", { 141 | action: "store_true", 142 | help: "Encode values using Base64 encoding before encrypting and decode values after decrypting" 143 | }); 144 | parser.add_argument("--path", { 145 | metavar: "", 146 | help: 'Only process values below the given YAML path. For the document {obj:{key:secret},other:[value1,value2]} use "--path=obj.key" to only process "secret"' 147 | }); 148 | parser.add_argument("--query", { 149 | metavar: "", 150 | help: "Output the value for the given YAML query path. Uses the same syntax as the --path option" 151 | }); 152 | parser.add_argument("--raw", { 153 | action: "store_true", 154 | help: "Encrypt/decrypt raw messages instead of YAML documents" 155 | }); 156 | parser.add_argument("-D", "--dir", { 157 | action: "store_true", 158 | help: "Allows to pass directories as input, process all files within the given directories (non-recursive)" 159 | }); 160 | parser.add_argument("-R", "--recursive", { 161 | action: "store_true", 162 | help: "Allows to pass directories as input, process all files within the given directories and subdirectories recursively" 163 | }); 164 | parser.add_argument("--continue", { 165 | action: "store_true", 166 | help: "Continue processing even when encryption/decryption of one or more files failed" 167 | }); 168 | parser.add_argument("--keep", { 169 | action: "store_true", 170 | help: "Keep the original files after encryption/decryption" 171 | }); 172 | parser.add_argument("-f", "--force", { 173 | action: "store_true", 174 | help: "Overwrite existing files" 175 | }); 176 | parser.add_argument("file", { 177 | nargs: "*", 178 | metavar: "", 179 | help: "Input file(s) to process" 180 | }); 181 | if ( 182 | (argv && argv.includes("--help")) || 183 | (process.argv && process.argv.includes("--help")) 184 | ) { 185 | parser.add_argument_group({ 186 | title: "Configuration file", 187 | description: 188 | "During startup, yaml-crypt will look for a configuration file " + 189 | '"config.yaml" or "config.yml" in the folder "$HOME/.yaml-crypt" and read keys from ' + 190 | 'the array "keys". Each key is expected to be an object with the required ' + 191 | 'attribute "key" which contains the raw key data and an optional attribute ' + 192 | '"name" with a custom name for that key.' 193 | }); 194 | parser.add_argument_group({ 195 | title: "Key sources", 196 | description: 197 | "Keys can be provided from multiple sources: configuration file, environment variables, key files and file descriptors. " + 198 | "When no explicit specifier is given, any arguments will be treated as key files. To select a specific source, " + 199 | 'specify "c:" or "config:" for configuration file, "e:" or "env:" for environment variables, "fd:" for file descriptors and "f:" for files. ' + 200 | 'For example, "yaml-crypt -k c:my-key -k e:MY_KEY -k fd:0 -k f:my.key" will read the key named "my-key" from ' + 201 | 'the configuration file, read a key from the environment variable "MY_KEY", read another key from file descriptor 0 (stdin) and another key from ' + 202 | 'the local file "my.key".' 203 | }); 204 | parser.add_argument_group({ 205 | title: "Decryption keys", 206 | description: 207 | "When no keys are given, decryption keys are read from the configuration file. " + 208 | "When no decryption keys are given, but an encryption key is given, that key will also be " + 209 | "used for decryption. " + 210 | "All provided decryption keys are tried, in order, until the data can be successfully decrypted. " + 211 | "If none of the available keys matches, the operation fails." 212 | }); 213 | parser.add_argument_group({ 214 | title: "Encryption keys", 215 | description: 216 | "When no encryption key is given and only one decryption key is available, that " + 217 | "key will be used for encryption. When editing a file and no encryption key is given, " + 218 | "the matching decryption key will be used to encrypt the modified data. " + 219 | 'In all other cases, an encryption key must be explicitly selected using "-K".' 220 | }); 221 | parser.epilog = 222 | "For more information, visit https://github.com/autoapply/yaml-crypt"; 223 | } else { 224 | parser.epilog = "For more details, specify --help"; 225 | } 226 | const args = parser.parse_args(argv); 227 | if (args.encrypt && args.decrypt) { 228 | throw new UsageError("cannot combine --encrypt and --decrypt!"); 229 | } 230 | if (args.raw && args.path) { 231 | throw new UsageError("cannot combine --raw and --path!"); 232 | } 233 | if (args.raw && args.query) { 234 | throw new UsageError("cannot combine --raw and --query!"); 235 | } 236 | if (args.edit && args.path) { 237 | throw new UsageError("cannot combine --edit and --path!"); 238 | } 239 | if (args.edit && args.query) { 240 | throw new UsageError("cannot combine --edit and --query!"); 241 | } 242 | if (args.edit && args.keep) { 243 | throw new UsageError("cannot combine --edit and --keep!"); 244 | } 245 | if (args.edit && args.encrypt) { 246 | throw new UsageError("cannot combine --edit and --encrypt!"); 247 | } 248 | if (args.edit && args.decrypt) { 249 | throw new UsageError("cannot combine --edit and --decrypt!"); 250 | } 251 | if (args.dir && args.recursive) { 252 | throw new UsageError("cannot combine --dir and --recursive!"); 253 | } 254 | if (args.edit && !args.file.length) { 255 | throw new UsageError("option --edit used, but no files given!"); 256 | } 257 | if ( 258 | !args.generate_key && 259 | !args.write_key && 260 | !args.k && 261 | (!config.keys || !config.keys.length) 262 | ) { 263 | throw new UsageError("no keys given and no default keys configured!"); 264 | } 265 | if (args.keep && !args.file.length) { 266 | throw new UsageError("option --keep used, but no files given!"); 267 | } 268 | if (args.query && args.file.length) { 269 | throw new UsageError("option --query only valid when reading from stdin!"); 270 | } 271 | if (args.query && !args.decrypt) { 272 | throw new UsageError("option --query must be combined with --decrypt!"); 273 | } 274 | if (args.generate_key && args.write_key) { 275 | throw new UsageError("cannot combine --generate-key and --write-key!"); 276 | } 277 | if (args.generate_key && args.encrypt) { 278 | throw new UsageError("cannot combine --generate-key and --encrypt!"); 279 | } 280 | if (args.generate_key && args.decrypt) { 281 | throw new UsageError("cannot combine --generate-key and --decrypt!"); 282 | } 283 | if (args.generate_key && args.file && args.file.length) { 284 | throw new UsageError("option --generate-key used, but files given!"); 285 | } 286 | if (args.write_key && args.encrypt) { 287 | throw new UsageError("cannot combine --write-key and --encrypt!"); 288 | } 289 | if (args.write_key && args.decrypt) { 290 | throw new UsageError("cannot combine --write-key and --decrypt!"); 291 | } 292 | if (args.write_key && args.file && args.file.length) { 293 | throw new UsageError("option --write-key used, but files given!"); 294 | } 295 | try { 296 | _run(args, config, options); 297 | } catch (e) { 298 | if (args.debug || e instanceof ConfigurationError) { 299 | throw e; 300 | } else { 301 | throw new UnknownError(e.message); 302 | } 303 | } 304 | } 305 | 306 | function _run(args, config, options) { 307 | let algorithm = null; 308 | for (const a of algorithms) { 309 | if (a === args.algorithm || a.startsWith(`${args.algorithm}:`)) { 310 | algorithm = a; 311 | break; 312 | } 313 | } 314 | if (args.algorithm && algorithm == null) { 315 | throw new UsageError(`unknown encryption algorithm: ${args.algorithm}`); 316 | } 317 | let input; 318 | if (options.stdin) { 319 | input = options.stdin; 320 | } else { 321 | input = process.stdin; 322 | } 323 | let output; 324 | if (options.stdout) { 325 | output = options.stdout; 326 | } else { 327 | output = process.stdout; 328 | output.on("error", err => { 329 | if (err && err.code === "EPIPE") { 330 | console.error("broken pipe"); 331 | } else { 332 | console.error("unknown I/O error!"); 333 | } 334 | }); 335 | } 336 | const configKeys = readConfigKeys(config); 337 | const keys = []; 338 | if (args.k) { 339 | keys.push(...args.k.map(k => readKey(configKeys, k))); 340 | } else { 341 | configKeys.forEach(k => 342 | keys.push({ source: `config:${k.name}`, key: k.key }) 343 | ); 344 | } 345 | const encryptionKey = args.K 346 | ? readKey(configKeys, args.K) 347 | : keys.length === 1 348 | ? keys[0] 349 | : null; 350 | if (args.generate_key) { 351 | const key = generateKey(algorithm); 352 | output.write(key); 353 | output.write("\n"); 354 | } else if (args.write_key) { 355 | const name = args.write_key; 356 | for (const key of configKeys) { 357 | if (key.name === name) { 358 | throw new UsageError(`key already exists: ${name}`); 359 | } 360 | } 361 | readInput(input, buf => { 362 | const key = buf.toString("utf8").trim(); 363 | if (key.length === 32) { 364 | writeNewKey(key, name); 365 | } else if (key.length > 0) { 366 | throw new UsageError(`key should be 32 bytes, but got ${key.length}`); 367 | } else { 368 | throw new UsageError("empty key given!"); 369 | } 370 | }); 371 | } else if (args.edit) { 372 | for (const file of args.file) { 373 | editFile(file, keys, encryptionKey, algorithm, args, config); 374 | } 375 | } else if (args.file.length) { 376 | for (const file of args.file) { 377 | processFileArg(file, keys, encryptionKey, algorithm, args, options); 378 | } 379 | } else { 380 | let encrypting; 381 | if (args.encrypt) { 382 | encrypting = true; 383 | } else if (args.decrypt) { 384 | encrypting = false; 385 | } else { 386 | throw new UsageError( 387 | "no input files, but no operation (--encrypt/--decrypt) given!" 388 | ); 389 | } 390 | if (encrypting) { 391 | checkEncryptionKey(keys, encryptionKey); 392 | } 393 | readInput(input, buf => { 394 | if (args.raw) { 395 | if (encrypting) { 396 | const str = args.base64 397 | ? buf.toString("base64") 398 | : buf.toString("utf8"); 399 | const result = encrypt(algorithm, encryptionKey.key, str); 400 | output.write(result); 401 | output.write("\n"); 402 | } else { 403 | const str = buf.toString("utf8"); 404 | const { key, decrypted } = tryDecrypt( 405 | algorithms, 406 | keys, 407 | (algorithm, key) => decrypt(algorithm, key.key, str) 408 | ); 409 | logDecryptionKey(args, key); 410 | const result = args.base64 411 | ? Buffer.from(decrypted, "base64").toString("utf8") 412 | : decrypted; 413 | output.write(result); 414 | } 415 | } else { 416 | const opts = { 417 | algorithm, 418 | base64: args.base64, 419 | path: args.path, 420 | callback: key => logDecryptionKey(args, key) 421 | }; 422 | const str = buf.toString("utf8"); 423 | const crypt = yamlcrypt({ keys, encryptionKey }); 424 | let result; 425 | if (encrypting) { 426 | result = crypt.encryptAll(str, opts); 427 | } else { 428 | const objs = crypt.decryptAll(str, opts); 429 | if (args.query) { 430 | const arr = []; 431 | for (const obj of objs) { 432 | walkValues( 433 | obj, 434 | args.query, 435 | () => true, 436 | v => arr.push(v) 437 | ); 438 | } 439 | result = 440 | arr 441 | .map(v => (typeof v === "string" ? v : JSON.stringify(v))) 442 | .join("\n") + "\n"; 443 | } else { 444 | result = dumpAll(objs); 445 | } 446 | } 447 | output.write(result); 448 | } 449 | }); 450 | } 451 | } 452 | 453 | function readInput(input, callback) { 454 | if ( 455 | typeof input === "string" || 456 | input instanceof String || 457 | Buffer.isBuffer(input) 458 | ) { 459 | try { 460 | callback(input); 461 | } catch (e) { 462 | handleError(e); 463 | } 464 | } else { 465 | const ret = []; 466 | let len = 0; 467 | input.on("readable", () => { 468 | let chunk; 469 | while ((chunk = input.read())) { 470 | ret.push(chunk); 471 | len += chunk.length; 472 | } 473 | }); 474 | input.on("end", () => { 475 | try { 476 | callback(Buffer.concat(ret, len)); 477 | } catch (e) { 478 | handleError(e); 479 | } 480 | }); 481 | } 482 | } 483 | 484 | function checkEncryptionKey(keys, encryptionKey) { 485 | if (!encryptionKey) { 486 | if (keys.length) { 487 | throw new UsageError( 488 | "encrypting, but multiple keys given! " + 489 | "Use -K to explicitly specify an encryption key." 490 | ); 491 | } else { 492 | throw new UsageError("encrypting, but no keys given!"); 493 | } 494 | } 495 | } 496 | 497 | function readConfigKeys(config) { 498 | const keys = []; 499 | if (Array.isArray(config.keys)) { 500 | for (const obj of config.keys) { 501 | if (obj.key) { 502 | let key; 503 | const type = typeof obj.key; 504 | if (type === "string") { 505 | key = obj.key.trim(); 506 | } else if (Buffer.isBuffer(obj.key)) { 507 | key = obj.key.toString("utf8").trim(); 508 | } else { 509 | throw new ConfigurationError(`key entry is not a string: ${type}`); 510 | } 511 | const name = obj.name || ""; 512 | keys.push({ key, name }); 513 | } else { 514 | throw new ConfigurationError("attribute key missing for key entry!"); 515 | } 516 | } 517 | } 518 | for (let i = 0; i < keys.length; i++) { 519 | for (let j = 0; j < keys.length; j++) { 520 | if (i !== j) { 521 | if (keys[i].name && keys[i].name === keys[j].name) { 522 | throw new ConfigurationError(`non-unique key name: ${keys[i].name}`); 523 | } 524 | } 525 | } 526 | } 527 | return keys; 528 | } 529 | 530 | function readKey(configKeys, key) { 531 | let prefix; 532 | let arg; 533 | if (key.includes(":") && !key.match(/^[A-Z]:\\/)) { 534 | const idx = key.indexOf(":"); 535 | prefix = key.substring(0, idx); 536 | arg = key.substring(idx + 1); 537 | } else { 538 | prefix = "f"; 539 | arg = key; 540 | } 541 | if (prefix === "c" || prefix === "config") { 542 | for (const k of configKeys) { 543 | if (k.name === arg) { 544 | return { source: `config:${k.name}`, key: k.key }; 545 | } 546 | } 547 | throw new UsageError(`key not found in configuration file: ${arg}`); 548 | } else if (prefix === "e" || prefix === "env") { 549 | const str = process.env[arg]; 550 | if (!str || !str.trim()) { 551 | throw new UsageError(`no such environment variable: ${arg}`); 552 | } 553 | return { source: `env:${arg}`, key: str.trim() }; 554 | } else if (prefix === "fd") { 555 | const fd = parseInt(arg); 556 | if (fd || fd === 0) { 557 | return { source: `fd:${arg}`, key: readFd(fd).trim() }; 558 | } else { 559 | throw new UsageError(`not a file descriptor: ${arg}`); 560 | } 561 | } else if (prefix === "f" || prefix === "file") { 562 | let raw; 563 | try { 564 | raw = fs.readFileSync(arg); 565 | } catch (e) { 566 | if (e.code === "ENOENT") { 567 | throw new UsageError(`key file does not exist: ${arg}`); 568 | } else { 569 | throw e; 570 | } 571 | } 572 | return { source: `file:${arg}`, key: raw.toString("utf8").trim() }; 573 | } else { 574 | throw new UsageError(`unknown key argument: ${key}`); 575 | } 576 | } 577 | 578 | function readFd(fd) { 579 | var buf = Buffer.alloc(1024); 580 | let str = ""; 581 | while (true) { 582 | var len = fs.readSync(fd, buf, 0, buf.length); 583 | if (!len) { 584 | break; 585 | } 586 | str += buf.toString("utf8", 0, len); 587 | } 588 | return str; 589 | } 590 | 591 | function writeNewKey(key, name) { 592 | const configHome = path.join(homedir(), ".yaml-crypt"); 593 | 594 | let file = null; 595 | let content = null; 596 | for (const filename of ["config.yaml", "config.yml"]) { 597 | try { 598 | file = path.join(configHome, filename); 599 | content = fs.readFileSync(file, "utf8"); 600 | break; 601 | } catch (e) { 602 | if (e.code === "ENOENT") { 603 | continue; 604 | } else { 605 | throw e; 606 | } 607 | } 608 | } 609 | 610 | if (content == null) { 611 | content = ""; 612 | file = path.join(configHome, "config.yaml"); 613 | fs.mkdirSync(configHome, { recursive: true, mode: 0o700 }); 614 | } 615 | 616 | const lf = content.includes("\r\n") ? "\r\n" : "\n"; 617 | 618 | // no YAML parsing, to keep file comments! 619 | if (content.length > 0 && !content.endsWith(lf)) { 620 | content += lf; 621 | } 622 | if (!content.split(lf).includes("keys:")) { 623 | content += `keys:${lf}`; 624 | } 625 | content += ` - name: '${name}'${lf} key: '${key}'${lf}`; 626 | 627 | fs.writeFileSync(file, content, { encoding: "utf8", mode: 0o600 }); 628 | } 629 | 630 | function plaintextFile(file) { 631 | return file.endsWith(".yaml") || file.endsWith(".yml"); 632 | } 633 | 634 | function encryptedFile(file) { 635 | return file.endsWith(".yaml-crypt") || file.endsWith(".yml-crypt"); 636 | } 637 | 638 | function processFileArg(file, keys, encryptionKey, algorithm, args, options) { 639 | const stat = fs.statSync(file); 640 | if (stat.isDirectory()) { 641 | if (args.dir || args.recursive) { 642 | walk(file, args.recursive, f => { 643 | if (args.encrypt && !plaintextFile(f)) { 644 | return; 645 | } else if (args.decrypt && !encryptedFile(f)) { 646 | return; 647 | } else if (!plaintextFile(f) && !encryptedFile(f)) { 648 | return; 649 | } else { 650 | processFile(f, keys, encryptionKey, algorithm, args, options); 651 | } 652 | }); 653 | } else { 654 | throw new UsageError( 655 | `directories will be skipped unless --dir or --recursive given: ${file}` 656 | ); 657 | } 658 | } else { 659 | processFile(file, keys, encryptionKey, algorithm, args, options); 660 | } 661 | } 662 | 663 | function processFile(file, keys, encryptionKey, algorithm, args, options) { 664 | try { 665 | doProcessFile(file, keys, encryptionKey, algorithm, args); 666 | } catch (e) { 667 | if (args["continue"]) { 668 | if (options.stderr) { 669 | options.stderr.write(`error: ${e.message}`); 670 | } else { 671 | console.error(`error: ${e.message}`); 672 | } 673 | } else { 674 | throw e; 675 | } 676 | } 677 | } 678 | 679 | function doProcessFile(file, keys, encryptionKey, algorithm, args) { 680 | let encrypting; 681 | if (plaintextFile(file)) { 682 | encrypting = true; 683 | } else if (encryptedFile(file)) { 684 | encrypting = false; 685 | } else { 686 | throw new UsageError(`unknown file extension: ${file}`); 687 | } 688 | if (encrypting && args.decrypt) { 689 | throw new UsageError(`decrypted file, but --decrypt given: ${file}`); 690 | } else if (!encrypting && args.encrypt) { 691 | throw new UsageError(`encrypted file, but --encrypt given: ${file}`); 692 | } 693 | if (encrypting) { 694 | checkEncryptionKey(keys, encryptionKey); 695 | } 696 | let content; 697 | try { 698 | content = fs.readFileSync(file); 699 | } catch (e) { 700 | if (e.code === "ENOENT") { 701 | throw new UsageError(`file does not exist: ${file}`); 702 | } else { 703 | throw e; 704 | } 705 | } 706 | const output = encrypting 707 | ? file + "-crypt" 708 | : file.substring(0, file.length - "-crypt".length); 709 | if (fs.existsSync(output) && !args.force) { 710 | throw new UsageError(`output file already exists: ${output}`); 711 | } 712 | 713 | const opts = { 714 | algorithm, 715 | base64: args.base64, 716 | path: args.path, 717 | raw: args.raw, 718 | callback: key => logDecryptionKey(args, key) 719 | }; 720 | const crypt = yamlcrypt({ keys, encryptionKey }); 721 | let result; 722 | if (encrypting) { 723 | result = crypt.encryptAll(content, opts); 724 | } else { 725 | const objs = crypt.decryptAll(content, opts); 726 | result = dumpAll(objs); 727 | } 728 | 729 | if (!args.keep) { 730 | fs.renameSync(file, output); 731 | } 732 | fs.writeFileSync(output, result); 733 | } 734 | 735 | function editFile(file, keys, encryptionKey, algorithm, args, config) { 736 | if (!encryptedFile(file)) { 737 | throw new UsageError( 738 | `unexpected extension, expecting .yaml-crypt or .yml-crypt: ${file}` 739 | ); 740 | } 741 | 742 | let content; 743 | try { 744 | content = fs.readFileSync(file); 745 | } catch (e) { 746 | if (e.code === "ENOENT") { 747 | throw new UsageError(`file does not exist: ${file}`); 748 | } else { 749 | throw e; 750 | } 751 | } 752 | 753 | const dir = path.dirname(path.resolve(file)); 754 | 755 | const editor = config["editor"] || process.env["EDITOR"] || "vim"; 756 | 757 | const tmpFile = tmp.fileSync({ 758 | tmpdir: dir, 759 | postfix: ".yaml", 760 | keep: true, 761 | discardDescriptor: true 762 | }); 763 | 764 | try { 765 | const opts = { base64: args.base64, algorithm: algorithm, raw: args.raw }; 766 | const crypt = yamlcrypt({ keys, encryptionKey }); 767 | const transformed = crypt.transform( 768 | content, 769 | (str, key) => { 770 | logDecryptionKey(args, key); 771 | 772 | fs.writeFileSync(tmpFile.name, str); 773 | 774 | childProcess.spawnSync(editor, [tmpFile.name], { stdio: "inherit" }); 775 | 776 | return fs.readFileSync(tmpFile.name); 777 | }, 778 | opts 779 | ); 780 | fs.writeFileSync(tmpFile.name, transformed); 781 | fs.renameSync(tmpFile.name, file); 782 | } finally { 783 | try { 784 | tmpFile.removeCallback(); 785 | } finally { 786 | if (fs.existsSync(tmpFile.name)) { 787 | fs.unlinkSync(tmpFile.name); 788 | } 789 | } 790 | } 791 | } 792 | 793 | function logDecryptionKey(args, key) { 794 | if (args.debug) { 795 | console.error("successfully decrypted using key:", key.source); 796 | } 797 | } 798 | 799 | class UnknownError extends Error {} 800 | 801 | class ConfigurationError extends Error {} 802 | 803 | class ExitError extends Error { 804 | constructor(status) { 805 | super(`Exit: ${status}`); 806 | this.status = status; 807 | } 808 | } 809 | 810 | module.exports.run = run; 811 | 812 | if (require.main === module) { 813 | main().catch(e => { 814 | process.exitCode = 1; 815 | console.error(e); 816 | }); 817 | } 818 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@aashutoshrathi/word-wrap@^1.2.3": 6 | version "1.2.6" 7 | resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" 8 | integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== 9 | 10 | "@ampproject/remapping@^2.2.0": 11 | version "2.2.1" 12 | resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" 13 | integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== 14 | dependencies: 15 | "@jridgewell/gen-mapping" "^0.3.0" 16 | "@jridgewell/trace-mapping" "^0.3.9" 17 | 18 | "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": 19 | version "7.23.5" 20 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" 21 | integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== 22 | dependencies: 23 | "@babel/highlight" "^7.23.4" 24 | chalk "^2.4.2" 25 | 26 | "@babel/compat-data@^7.23.5": 27 | version "7.23.5" 28 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" 29 | integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== 30 | 31 | "@babel/core@^7.7.5": 32 | version "7.23.6" 33 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" 34 | integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== 35 | dependencies: 36 | "@ampproject/remapping" "^2.2.0" 37 | "@babel/code-frame" "^7.23.5" 38 | "@babel/generator" "^7.23.6" 39 | "@babel/helper-compilation-targets" "^7.23.6" 40 | "@babel/helper-module-transforms" "^7.23.3" 41 | "@babel/helpers" "^7.23.6" 42 | "@babel/parser" "^7.23.6" 43 | "@babel/template" "^7.22.15" 44 | "@babel/traverse" "^7.23.6" 45 | "@babel/types" "^7.23.6" 46 | convert-source-map "^2.0.0" 47 | debug "^4.1.0" 48 | gensync "^1.0.0-beta.2" 49 | json5 "^2.2.3" 50 | semver "^6.3.1" 51 | 52 | "@babel/generator@^7.23.6": 53 | version "7.23.6" 54 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" 55 | integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== 56 | dependencies: 57 | "@babel/types" "^7.23.6" 58 | "@jridgewell/gen-mapping" "^0.3.2" 59 | "@jridgewell/trace-mapping" "^0.3.17" 60 | jsesc "^2.5.1" 61 | 62 | "@babel/helper-compilation-targets@^7.23.6": 63 | version "7.23.6" 64 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" 65 | integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== 66 | dependencies: 67 | "@babel/compat-data" "^7.23.5" 68 | "@babel/helper-validator-option" "^7.23.5" 69 | browserslist "^4.22.2" 70 | lru-cache "^5.1.1" 71 | semver "^6.3.1" 72 | 73 | "@babel/helper-environment-visitor@^7.22.20": 74 | version "7.22.20" 75 | resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" 76 | integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== 77 | 78 | "@babel/helper-function-name@^7.23.0": 79 | version "7.23.0" 80 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" 81 | integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== 82 | dependencies: 83 | "@babel/template" "^7.22.15" 84 | "@babel/types" "^7.23.0" 85 | 86 | "@babel/helper-hoist-variables@^7.22.5": 87 | version "7.22.5" 88 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" 89 | integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== 90 | dependencies: 91 | "@babel/types" "^7.22.5" 92 | 93 | "@babel/helper-module-imports@^7.22.15": 94 | version "7.22.15" 95 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" 96 | integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== 97 | dependencies: 98 | "@babel/types" "^7.22.15" 99 | 100 | "@babel/helper-module-transforms@^7.23.3": 101 | version "7.23.3" 102 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" 103 | integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== 104 | dependencies: 105 | "@babel/helper-environment-visitor" "^7.22.20" 106 | "@babel/helper-module-imports" "^7.22.15" 107 | "@babel/helper-simple-access" "^7.22.5" 108 | "@babel/helper-split-export-declaration" "^7.22.6" 109 | "@babel/helper-validator-identifier" "^7.22.20" 110 | 111 | "@babel/helper-simple-access@^7.22.5": 112 | version "7.22.5" 113 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" 114 | integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== 115 | dependencies: 116 | "@babel/types" "^7.22.5" 117 | 118 | "@babel/helper-split-export-declaration@^7.22.6": 119 | version "7.22.6" 120 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" 121 | integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== 122 | dependencies: 123 | "@babel/types" "^7.22.5" 124 | 125 | "@babel/helper-string-parser@^7.23.4": 126 | version "7.23.4" 127 | resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" 128 | integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== 129 | 130 | "@babel/helper-validator-identifier@^7.22.20": 131 | version "7.22.20" 132 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" 133 | integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== 134 | 135 | "@babel/helper-validator-option@^7.23.5": 136 | version "7.23.5" 137 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" 138 | integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== 139 | 140 | "@babel/helpers@^7.23.6": 141 | version "7.23.6" 142 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" 143 | integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== 144 | dependencies: 145 | "@babel/template" "^7.22.15" 146 | "@babel/traverse" "^7.23.6" 147 | "@babel/types" "^7.23.6" 148 | 149 | "@babel/highlight@^7.23.4": 150 | version "7.23.4" 151 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" 152 | integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== 153 | dependencies: 154 | "@babel/helper-validator-identifier" "^7.22.20" 155 | chalk "^2.4.2" 156 | js-tokens "^4.0.0" 157 | 158 | "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": 159 | version "7.23.6" 160 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" 161 | integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== 162 | 163 | "@babel/template@^7.22.15": 164 | version "7.22.15" 165 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" 166 | integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== 167 | dependencies: 168 | "@babel/code-frame" "^7.22.13" 169 | "@babel/parser" "^7.22.15" 170 | "@babel/types" "^7.22.15" 171 | 172 | "@babel/traverse@^7.23.6": 173 | version "7.23.6" 174 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" 175 | integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== 176 | dependencies: 177 | "@babel/code-frame" "^7.23.5" 178 | "@babel/generator" "^7.23.6" 179 | "@babel/helper-environment-visitor" "^7.22.20" 180 | "@babel/helper-function-name" "^7.23.0" 181 | "@babel/helper-hoist-variables" "^7.22.5" 182 | "@babel/helper-split-export-declaration" "^7.22.6" 183 | "@babel/parser" "^7.23.6" 184 | "@babel/types" "^7.23.6" 185 | debug "^4.3.1" 186 | globals "^11.1.0" 187 | 188 | "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6": 189 | version "7.23.6" 190 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" 191 | integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== 192 | dependencies: 193 | "@babel/helper-string-parser" "^7.23.4" 194 | "@babel/helper-validator-identifier" "^7.22.20" 195 | to-fast-properties "^2.0.0" 196 | 197 | "@eslint-community/eslint-utils@^4.2.0": 198 | version "4.4.0" 199 | resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" 200 | integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== 201 | dependencies: 202 | eslint-visitor-keys "^3.3.0" 203 | 204 | "@eslint-community/regexpp@^4.6.1": 205 | version "4.10.0" 206 | resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" 207 | integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== 208 | 209 | "@eslint/eslintrc@^2.1.4": 210 | version "2.1.4" 211 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" 212 | integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== 213 | dependencies: 214 | ajv "^6.12.4" 215 | debug "^4.3.2" 216 | espree "^9.6.0" 217 | globals "^13.19.0" 218 | ignore "^5.2.0" 219 | import-fresh "^3.2.1" 220 | js-yaml "^4.1.0" 221 | minimatch "^3.1.2" 222 | strip-json-comments "^3.1.1" 223 | 224 | "@eslint/js@8.55.0": 225 | version "8.55.0" 226 | resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.55.0.tgz#b721d52060f369aa259cf97392403cb9ce892ec6" 227 | integrity sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA== 228 | 229 | "@humanwhocodes/config-array@^0.11.13": 230 | version "0.11.13" 231 | resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" 232 | integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== 233 | dependencies: 234 | "@humanwhocodes/object-schema" "^2.0.1" 235 | debug "^4.1.1" 236 | minimatch "^3.0.5" 237 | 238 | "@humanwhocodes/module-importer@^1.0.1": 239 | version "1.0.1" 240 | resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" 241 | integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 242 | 243 | "@humanwhocodes/object-schema@^2.0.1": 244 | version "2.0.1" 245 | resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" 246 | integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== 247 | 248 | "@istanbuljs/load-nyc-config@^1.0.0": 249 | version "1.1.0" 250 | resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" 251 | integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== 252 | dependencies: 253 | camelcase "^5.3.1" 254 | find-up "^4.1.0" 255 | get-package-type "^0.1.0" 256 | js-yaml "^3.13.1" 257 | resolve-from "^5.0.0" 258 | 259 | "@istanbuljs/schema@^0.1.2": 260 | version "0.1.3" 261 | resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" 262 | integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== 263 | 264 | "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": 265 | version "0.3.3" 266 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" 267 | integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== 268 | dependencies: 269 | "@jridgewell/set-array" "^1.0.1" 270 | "@jridgewell/sourcemap-codec" "^1.4.10" 271 | "@jridgewell/trace-mapping" "^0.3.9" 272 | 273 | "@jridgewell/resolve-uri@^3.1.0": 274 | version "3.1.1" 275 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" 276 | integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== 277 | 278 | "@jridgewell/set-array@^1.0.1": 279 | version "1.1.2" 280 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" 281 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== 282 | 283 | "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": 284 | version "1.4.15" 285 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" 286 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== 287 | 288 | "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": 289 | version "0.3.20" 290 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" 291 | integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== 292 | dependencies: 293 | "@jridgewell/resolve-uri" "^3.1.0" 294 | "@jridgewell/sourcemap-codec" "^1.4.14" 295 | 296 | "@nodelib/fs.scandir@2.1.5": 297 | version "2.1.5" 298 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 299 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 300 | dependencies: 301 | "@nodelib/fs.stat" "2.0.5" 302 | run-parallel "^1.1.9" 303 | 304 | "@nodelib/fs.stat@2.0.5": 305 | version "2.0.5" 306 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 307 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 308 | 309 | "@nodelib/fs.walk@^1.2.8": 310 | version "1.2.8" 311 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 312 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 313 | dependencies: 314 | "@nodelib/fs.scandir" "2.1.5" 315 | fastq "^1.6.0" 316 | 317 | "@ungap/structured-clone@^1.2.0": 318 | version "1.2.0" 319 | resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" 320 | integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== 321 | 322 | acorn-jsx@^5.3.2: 323 | version "5.3.2" 324 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 325 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 326 | 327 | acorn@^8.9.0: 328 | version "8.11.2" 329 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" 330 | integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== 331 | 332 | aggregate-error@^3.0.0: 333 | version "3.1.0" 334 | resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" 335 | integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== 336 | dependencies: 337 | clean-stack "^2.0.0" 338 | indent-string "^4.0.0" 339 | 340 | ajv@^6.12.3, ajv@^6.12.4: 341 | version "6.12.6" 342 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 343 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 344 | dependencies: 345 | fast-deep-equal "^3.1.1" 346 | fast-json-stable-stringify "^2.0.0" 347 | json-schema-traverse "^0.4.1" 348 | uri-js "^4.2.2" 349 | 350 | ansi-colors@4.1.1: 351 | version "4.1.1" 352 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 353 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 354 | 355 | ansi-regex@^5.0.1: 356 | version "5.0.1" 357 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 358 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 359 | 360 | ansi-styles@^3.2.1: 361 | version "3.2.1" 362 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 363 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 364 | dependencies: 365 | color-convert "^1.9.0" 366 | 367 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 368 | version "4.3.0" 369 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 370 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 371 | dependencies: 372 | color-convert "^2.0.1" 373 | 374 | anymatch@~3.1.2: 375 | version "3.1.3" 376 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 377 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 378 | dependencies: 379 | normalize-path "^3.0.0" 380 | picomatch "^2.0.4" 381 | 382 | append-transform@^2.0.0: 383 | version "2.0.0" 384 | resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" 385 | integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== 386 | dependencies: 387 | default-require-extensions "^3.0.0" 388 | 389 | archy@^1.0.0: 390 | version "1.0.0" 391 | resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" 392 | integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== 393 | 394 | argparse@^1.0.7: 395 | version "1.0.10" 396 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 397 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 398 | dependencies: 399 | sprintf-js "~1.0.2" 400 | 401 | argparse@^2.0.1: 402 | version "2.0.1" 403 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 404 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 405 | 406 | asn1@~0.2.3: 407 | version "0.2.6" 408 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" 409 | integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== 410 | dependencies: 411 | safer-buffer "~2.1.0" 412 | 413 | assert-plus@1.0.0, assert-plus@^1.0.0: 414 | version "1.0.0" 415 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 416 | integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== 417 | 418 | assertion-error@^1.1.0: 419 | version "1.1.0" 420 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 421 | integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== 422 | 423 | asynckit@^0.4.0: 424 | version "0.4.0" 425 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 426 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 427 | 428 | aws-sign2@~0.7.0: 429 | version "0.7.0" 430 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 431 | integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== 432 | 433 | aws4@^1.8.0: 434 | version "1.12.0" 435 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" 436 | integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== 437 | 438 | balanced-match@^1.0.0: 439 | version "1.0.2" 440 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 441 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 442 | 443 | base-x@^4.0.0: 444 | version "4.0.0" 445 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" 446 | integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== 447 | 448 | bcrypt-pbkdf@^1.0.0: 449 | version "1.0.2" 450 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 451 | integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== 452 | dependencies: 453 | tweetnacl "^0.14.3" 454 | 455 | binary-extensions@^2.0.0: 456 | version "2.2.0" 457 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 458 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 459 | 460 | brace-expansion@^1.1.7: 461 | version "1.1.11" 462 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 463 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 464 | dependencies: 465 | balanced-match "^1.0.0" 466 | concat-map "0.0.1" 467 | 468 | brace-expansion@^2.0.1: 469 | version "2.0.1" 470 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 471 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 472 | dependencies: 473 | balanced-match "^1.0.0" 474 | 475 | braces@~3.0.2: 476 | version "3.0.2" 477 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 478 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 479 | dependencies: 480 | fill-range "^7.0.1" 481 | 482 | branca@^0.5.0: 483 | version "0.5.0" 484 | resolved "https://registry.yarnpkg.com/branca/-/branca-0.5.0.tgz#923bf2eaa7d83d76221dd2f50e3c7d53ddd3dc66" 485 | integrity sha512-+pFdcuMULjnmiH5PMrKEzVtYkPMIEFVwZD4whEPTZ1d90GXPVKjeAN3JfZwq3AFB5CJvz+jCOzxEtNvyUj74iQ== 486 | dependencies: 487 | base-x "^4.0.0" 488 | bufferpack "^0.0.6" 489 | libsodium-wrappers "^0.5.2" 490 | 491 | browser-stdout@1.3.1: 492 | version "1.3.1" 493 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 494 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 495 | 496 | browserslist@^4.22.2: 497 | version "4.22.2" 498 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" 499 | integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== 500 | dependencies: 501 | caniuse-lite "^1.0.30001565" 502 | electron-to-chromium "^1.4.601" 503 | node-releases "^2.0.14" 504 | update-browserslist-db "^1.0.13" 505 | 506 | bufferpack@^0.0.6: 507 | version "0.0.6" 508 | resolved "https://registry.yarnpkg.com/bufferpack/-/bufferpack-0.0.6.tgz#fb3d8738a0e1e4e03bcff99f9a75f9ec18a9d73e" 509 | integrity sha512-MTWvLHElqczrIVhge9qHtqgNigJFyh0+tCDId5yCbFAfuekHWIG+uAgvoHVflwrDPuY/e47JE1ki5qcM7w4uLg== 510 | 511 | caching-transform@^4.0.0: 512 | version "4.0.0" 513 | resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" 514 | integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== 515 | dependencies: 516 | hasha "^5.0.0" 517 | make-dir "^3.0.0" 518 | package-hash "^4.0.0" 519 | write-file-atomic "^3.0.0" 520 | 521 | callsites@^3.0.0: 522 | version "3.1.0" 523 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 524 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 525 | 526 | camelcase@^5.0.0, camelcase@^5.3.1: 527 | version "5.3.1" 528 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 529 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 530 | 531 | camelcase@^6.0.0: 532 | version "6.3.0" 533 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 534 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 535 | 536 | caniuse-lite@^1.0.30001565: 537 | version "1.0.30001568" 538 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz#53fa9297273c9a977a560663f48cbea1767518b7" 539 | integrity sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A== 540 | 541 | caseless@~0.12.0: 542 | version "0.12.0" 543 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 544 | integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== 545 | 546 | chai@^4.3.10: 547 | version "4.3.10" 548 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" 549 | integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== 550 | dependencies: 551 | assertion-error "^1.1.0" 552 | check-error "^1.0.3" 553 | deep-eql "^4.1.3" 554 | get-func-name "^2.0.2" 555 | loupe "^2.3.6" 556 | pathval "^1.1.1" 557 | type-detect "^4.0.8" 558 | 559 | chalk@^2.4.2: 560 | version "2.4.2" 561 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 562 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 563 | dependencies: 564 | ansi-styles "^3.2.1" 565 | escape-string-regexp "^1.0.5" 566 | supports-color "^5.3.0" 567 | 568 | chalk@^4.0.0, chalk@^4.1.0: 569 | version "4.1.2" 570 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 571 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 572 | dependencies: 573 | ansi-styles "^4.1.0" 574 | supports-color "^7.1.0" 575 | 576 | check-error@^1.0.3: 577 | version "1.0.3" 578 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" 579 | integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== 580 | dependencies: 581 | get-func-name "^2.0.2" 582 | 583 | chokidar@3.5.3: 584 | version "3.5.3" 585 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 586 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 587 | dependencies: 588 | anymatch "~3.1.2" 589 | braces "~3.0.2" 590 | glob-parent "~5.1.2" 591 | is-binary-path "~2.1.0" 592 | is-glob "~4.0.1" 593 | normalize-path "~3.0.0" 594 | readdirp "~3.6.0" 595 | optionalDependencies: 596 | fsevents "~2.3.2" 597 | 598 | clean-stack@^2.0.0: 599 | version "2.2.0" 600 | resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" 601 | integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== 602 | 603 | cliui@^6.0.0: 604 | version "6.0.0" 605 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" 606 | integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== 607 | dependencies: 608 | string-width "^4.2.0" 609 | strip-ansi "^6.0.0" 610 | wrap-ansi "^6.2.0" 611 | 612 | cliui@^7.0.2: 613 | version "7.0.4" 614 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 615 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 616 | dependencies: 617 | string-width "^4.2.0" 618 | strip-ansi "^6.0.0" 619 | wrap-ansi "^7.0.0" 620 | 621 | color-convert@^1.9.0: 622 | version "1.9.3" 623 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 624 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 625 | dependencies: 626 | color-name "1.1.3" 627 | 628 | color-convert@^2.0.1: 629 | version "2.0.1" 630 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 631 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 632 | dependencies: 633 | color-name "~1.1.4" 634 | 635 | color-name@1.1.3: 636 | version "1.1.3" 637 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 638 | integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== 639 | 640 | color-name@~1.1.4: 641 | version "1.1.4" 642 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 643 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 644 | 645 | combined-stream@^1.0.6, combined-stream@~1.0.6: 646 | version "1.0.8" 647 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 648 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 649 | dependencies: 650 | delayed-stream "~1.0.0" 651 | 652 | commondir@^1.0.1: 653 | version "1.0.1" 654 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 655 | integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== 656 | 657 | concat-map@0.0.1: 658 | version "0.0.1" 659 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 660 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 661 | 662 | convert-source-map@^1.7.0: 663 | version "1.9.0" 664 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" 665 | integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== 666 | 667 | convert-source-map@^2.0.0: 668 | version "2.0.0" 669 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" 670 | integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== 671 | 672 | core-util-is@1.0.2: 673 | version "1.0.2" 674 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 675 | integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== 676 | 677 | coveralls@^3.1.1: 678 | version "3.1.1" 679 | resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" 680 | integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== 681 | dependencies: 682 | js-yaml "^3.13.1" 683 | lcov-parse "^1.0.0" 684 | log-driver "^1.2.7" 685 | minimist "^1.2.5" 686 | request "^2.88.2" 687 | 688 | cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: 689 | version "7.0.3" 690 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 691 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 692 | dependencies: 693 | path-key "^3.1.0" 694 | shebang-command "^2.0.0" 695 | which "^2.0.1" 696 | 697 | crypto-js@~3.1.2-1: 698 | version "3.1.8" 699 | resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" 700 | integrity sha512-4E+PJNbUbBrzQLB9Vw86eaF5xZ8MB6dw4aaZ67YhLNduTmqJ5AziuLrYikPWHJkC59DYZp+cyj+qg3vBE8OnOQ== 701 | 702 | dashdash@^1.12.0: 703 | version "1.14.1" 704 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 705 | integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== 706 | dependencies: 707 | assert-plus "^1.0.0" 708 | 709 | debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: 710 | version "4.3.4" 711 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 712 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 713 | dependencies: 714 | ms "2.1.2" 715 | 716 | decamelize@^1.2.0: 717 | version "1.2.0" 718 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 719 | integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== 720 | 721 | decamelize@^4.0.0: 722 | version "4.0.0" 723 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 724 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 725 | 726 | deep-eql@^4.1.3: 727 | version "4.1.3" 728 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" 729 | integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== 730 | dependencies: 731 | type-detect "^4.0.0" 732 | 733 | deep-is@^0.1.3: 734 | version "0.1.4" 735 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 736 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 737 | 738 | default-require-extensions@^3.0.0: 739 | version "3.0.1" 740 | resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.1.tgz#bfae00feeaeada68c2ae256c62540f60b80625bd" 741 | integrity sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw== 742 | dependencies: 743 | strip-bom "^4.0.0" 744 | 745 | delayed-stream@~1.0.0: 746 | version "1.0.0" 747 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 748 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 749 | 750 | diff@5.0.0: 751 | version "5.0.0" 752 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 753 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 754 | 755 | doctrine@^3.0.0: 756 | version "3.0.0" 757 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 758 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 759 | dependencies: 760 | esutils "^2.0.2" 761 | 762 | ecc-jsbn@~0.1.1: 763 | version "0.1.2" 764 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 765 | integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== 766 | dependencies: 767 | jsbn "~0.1.0" 768 | safer-buffer "^2.1.0" 769 | 770 | electron-to-chromium@^1.4.601: 771 | version "1.4.611" 772 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.611.tgz#92d3a8f03110fbf5f99b054da97825f994fa480a" 773 | integrity sha512-ZtRpDxrjHapOwxtv+nuth5ByB8clyn8crVynmRNGO3wG3LOp8RTcyZDqwaI6Ng6y8FCK2hVZmJoqwCskKbNMaw== 774 | 775 | emoji-regex@^8.0.0: 776 | version "8.0.0" 777 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 778 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 779 | 780 | es6-error@^4.0.1: 781 | version "4.1.1" 782 | resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" 783 | integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== 784 | 785 | escalade@^3.1.1: 786 | version "3.1.1" 787 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 788 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 789 | 790 | escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: 791 | version "4.0.0" 792 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 793 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 794 | 795 | escape-string-regexp@^1.0.5: 796 | version "1.0.5" 797 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 798 | integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== 799 | 800 | eslint-scope@^7.2.2: 801 | version "7.2.2" 802 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" 803 | integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== 804 | dependencies: 805 | esrecurse "^4.3.0" 806 | estraverse "^5.2.0" 807 | 808 | eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: 809 | version "3.4.3" 810 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" 811 | integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== 812 | 813 | eslint@^8.55.0: 814 | version "8.55.0" 815 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.55.0.tgz#078cb7b847d66f2c254ea1794fa395bf8e7e03f8" 816 | integrity sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA== 817 | dependencies: 818 | "@eslint-community/eslint-utils" "^4.2.0" 819 | "@eslint-community/regexpp" "^4.6.1" 820 | "@eslint/eslintrc" "^2.1.4" 821 | "@eslint/js" "8.55.0" 822 | "@humanwhocodes/config-array" "^0.11.13" 823 | "@humanwhocodes/module-importer" "^1.0.1" 824 | "@nodelib/fs.walk" "^1.2.8" 825 | "@ungap/structured-clone" "^1.2.0" 826 | ajv "^6.12.4" 827 | chalk "^4.0.0" 828 | cross-spawn "^7.0.2" 829 | debug "^4.3.2" 830 | doctrine "^3.0.0" 831 | escape-string-regexp "^4.0.0" 832 | eslint-scope "^7.2.2" 833 | eslint-visitor-keys "^3.4.3" 834 | espree "^9.6.1" 835 | esquery "^1.4.2" 836 | esutils "^2.0.2" 837 | fast-deep-equal "^3.1.3" 838 | file-entry-cache "^6.0.1" 839 | find-up "^5.0.0" 840 | glob-parent "^6.0.2" 841 | globals "^13.19.0" 842 | graphemer "^1.4.0" 843 | ignore "^5.2.0" 844 | imurmurhash "^0.1.4" 845 | is-glob "^4.0.0" 846 | is-path-inside "^3.0.3" 847 | js-yaml "^4.1.0" 848 | json-stable-stringify-without-jsonify "^1.0.1" 849 | levn "^0.4.1" 850 | lodash.merge "^4.6.2" 851 | minimatch "^3.1.2" 852 | natural-compare "^1.4.0" 853 | optionator "^0.9.3" 854 | strip-ansi "^6.0.1" 855 | text-table "^0.2.0" 856 | 857 | espree@^9.6.0, espree@^9.6.1: 858 | version "9.6.1" 859 | resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" 860 | integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== 861 | dependencies: 862 | acorn "^8.9.0" 863 | acorn-jsx "^5.3.2" 864 | eslint-visitor-keys "^3.4.1" 865 | 866 | esprima@^4.0.0: 867 | version "4.0.1" 868 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 869 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 870 | 871 | esquery@^1.4.2: 872 | version "1.5.0" 873 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" 874 | integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== 875 | dependencies: 876 | estraverse "^5.1.0" 877 | 878 | esrecurse@^4.3.0: 879 | version "4.3.0" 880 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 881 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 882 | dependencies: 883 | estraverse "^5.2.0" 884 | 885 | estraverse@^5.1.0, estraverse@^5.2.0: 886 | version "5.3.0" 887 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 888 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 889 | 890 | esutils@^2.0.2: 891 | version "2.0.3" 892 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 893 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 894 | 895 | extend@~3.0.2: 896 | version "3.0.2" 897 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 898 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 899 | 900 | extsprintf@1.3.0: 901 | version "1.3.0" 902 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 903 | integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== 904 | 905 | extsprintf@^1.2.0: 906 | version "1.4.1" 907 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" 908 | integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== 909 | 910 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 911 | version "3.1.3" 912 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 913 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 914 | 915 | fast-json-stable-stringify@^2.0.0: 916 | version "2.1.0" 917 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 918 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 919 | 920 | fast-levenshtein@^2.0.6: 921 | version "2.0.6" 922 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 923 | integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 924 | 925 | fastq@^1.6.0: 926 | version "1.15.0" 927 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" 928 | integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== 929 | dependencies: 930 | reusify "^1.0.4" 931 | 932 | fernet@^0.4.0: 933 | version "0.4.0" 934 | resolved "https://registry.yarnpkg.com/fernet/-/fernet-0.4.0.tgz#95d10a3660bf1ccfb4964687508ec2e2ba5eda25" 935 | integrity sha512-FJgmKoMeG4eoM+bEbMyTzPx9US4W+sw4D0i6jSWSKHFYlFZv92UIWi6a/w6MEf2JNSO+Mth/T+u+d/ye1zwN9A== 936 | dependencies: 937 | crypto-js "~3.1.2-1" 938 | urlsafe-base64 "1.0.0" 939 | 940 | file-entry-cache@^6.0.1: 941 | version "6.0.1" 942 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" 943 | integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== 944 | dependencies: 945 | flat-cache "^3.0.4" 946 | 947 | fill-range@^7.0.1: 948 | version "7.0.1" 949 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 950 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 951 | dependencies: 952 | to-regex-range "^5.0.1" 953 | 954 | find-cache-dir@^3.2.0: 955 | version "3.3.2" 956 | resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" 957 | integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== 958 | dependencies: 959 | commondir "^1.0.1" 960 | make-dir "^3.0.2" 961 | pkg-dir "^4.1.0" 962 | 963 | find-up@5.0.0, find-up@^5.0.0: 964 | version "5.0.0" 965 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 966 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 967 | dependencies: 968 | locate-path "^6.0.0" 969 | path-exists "^4.0.0" 970 | 971 | find-up@^4.0.0, find-up@^4.1.0: 972 | version "4.1.0" 973 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 974 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 975 | dependencies: 976 | locate-path "^5.0.0" 977 | path-exists "^4.0.0" 978 | 979 | flat-cache@^3.0.4: 980 | version "3.2.0" 981 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" 982 | integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== 983 | dependencies: 984 | flatted "^3.2.9" 985 | keyv "^4.5.3" 986 | rimraf "^3.0.2" 987 | 988 | flat@^5.0.2: 989 | version "5.0.2" 990 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 991 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 992 | 993 | flatted@^3.2.9: 994 | version "3.2.9" 995 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" 996 | integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== 997 | 998 | foreground-child@^2.0.0: 999 | version "2.0.0" 1000 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" 1001 | integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== 1002 | dependencies: 1003 | cross-spawn "^7.0.0" 1004 | signal-exit "^3.0.2" 1005 | 1006 | forever-agent@~0.6.1: 1007 | version "0.6.1" 1008 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 1009 | integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== 1010 | 1011 | form-data@~2.3.2: 1012 | version "2.3.3" 1013 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 1014 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 1015 | dependencies: 1016 | asynckit "^0.4.0" 1017 | combined-stream "^1.0.6" 1018 | mime-types "^2.1.12" 1019 | 1020 | fromentries@^1.2.0: 1021 | version "1.3.2" 1022 | resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" 1023 | integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== 1024 | 1025 | fs.realpath@^1.0.0: 1026 | version "1.0.0" 1027 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 1028 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 1029 | 1030 | fsevents@~2.3.2: 1031 | version "2.3.3" 1032 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 1033 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 1034 | 1035 | gensync@^1.0.0-beta.2: 1036 | version "1.0.0-beta.2" 1037 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" 1038 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 1039 | 1040 | get-caller-file@^2.0.1, get-caller-file@^2.0.5: 1041 | version "2.0.5" 1042 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 1043 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 1044 | 1045 | get-func-name@^2.0.1, get-func-name@^2.0.2: 1046 | version "2.0.2" 1047 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" 1048 | integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== 1049 | 1050 | get-package-type@^0.1.0: 1051 | version "0.1.0" 1052 | resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" 1053 | integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== 1054 | 1055 | getpass@^0.1.1: 1056 | version "0.1.7" 1057 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 1058 | integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== 1059 | dependencies: 1060 | assert-plus "^1.0.0" 1061 | 1062 | glob-parent@^6.0.2: 1063 | version "6.0.2" 1064 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 1065 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 1066 | dependencies: 1067 | is-glob "^4.0.3" 1068 | 1069 | glob-parent@~5.1.2: 1070 | version "5.1.2" 1071 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 1072 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 1073 | dependencies: 1074 | is-glob "^4.0.1" 1075 | 1076 | glob@7.2.0: 1077 | version "7.2.0" 1078 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 1079 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 1080 | dependencies: 1081 | fs.realpath "^1.0.0" 1082 | inflight "^1.0.4" 1083 | inherits "2" 1084 | minimatch "^3.0.4" 1085 | once "^1.3.0" 1086 | path-is-absolute "^1.0.0" 1087 | 1088 | glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: 1089 | version "7.2.3" 1090 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 1091 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 1092 | dependencies: 1093 | fs.realpath "^1.0.0" 1094 | inflight "^1.0.4" 1095 | inherits "2" 1096 | minimatch "^3.1.1" 1097 | once "^1.3.0" 1098 | path-is-absolute "^1.0.0" 1099 | 1100 | globals@^11.1.0: 1101 | version "11.12.0" 1102 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 1103 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 1104 | 1105 | globals@^13.19.0: 1106 | version "13.24.0" 1107 | resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" 1108 | integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== 1109 | dependencies: 1110 | type-fest "^0.20.2" 1111 | 1112 | graceful-fs@^4.1.15: 1113 | version "4.2.11" 1114 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 1115 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 1116 | 1117 | graphemer@^1.4.0: 1118 | version "1.4.0" 1119 | resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" 1120 | integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== 1121 | 1122 | har-schema@^2.0.0: 1123 | version "2.0.0" 1124 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 1125 | integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== 1126 | 1127 | har-validator@~5.1.3: 1128 | version "5.1.5" 1129 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" 1130 | integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== 1131 | dependencies: 1132 | ajv "^6.12.3" 1133 | har-schema "^2.0.0" 1134 | 1135 | has-flag@^3.0.0: 1136 | version "3.0.0" 1137 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 1138 | integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== 1139 | 1140 | has-flag@^4.0.0: 1141 | version "4.0.0" 1142 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 1143 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 1144 | 1145 | hasha@^5.0.0: 1146 | version "5.2.2" 1147 | resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" 1148 | integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== 1149 | dependencies: 1150 | is-stream "^2.0.0" 1151 | type-fest "^0.8.0" 1152 | 1153 | he@1.2.0: 1154 | version "1.2.0" 1155 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 1156 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 1157 | 1158 | html-escaper@^2.0.0: 1159 | version "2.0.2" 1160 | resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" 1161 | integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== 1162 | 1163 | http-signature@~1.2.0: 1164 | version "1.2.0" 1165 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 1166 | integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== 1167 | dependencies: 1168 | assert-plus "^1.0.0" 1169 | jsprim "^1.2.2" 1170 | sshpk "^1.7.0" 1171 | 1172 | ignore@^5.2.0: 1173 | version "5.3.0" 1174 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" 1175 | integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== 1176 | 1177 | import-fresh@^3.2.1: 1178 | version "3.3.0" 1179 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 1180 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 1181 | dependencies: 1182 | parent-module "^1.0.0" 1183 | resolve-from "^4.0.0" 1184 | 1185 | imurmurhash@^0.1.4: 1186 | version "0.1.4" 1187 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 1188 | integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 1189 | 1190 | indent-string@^4.0.0: 1191 | version "4.0.0" 1192 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 1193 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 1194 | 1195 | inflight@^1.0.4: 1196 | version "1.0.6" 1197 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 1198 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 1199 | dependencies: 1200 | once "^1.3.0" 1201 | wrappy "1" 1202 | 1203 | inherits@2: 1204 | version "2.0.4" 1205 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 1206 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 1207 | 1208 | is-binary-path@~2.1.0: 1209 | version "2.1.0" 1210 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 1211 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 1212 | dependencies: 1213 | binary-extensions "^2.0.0" 1214 | 1215 | is-extglob@^2.1.1: 1216 | version "2.1.1" 1217 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 1218 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 1219 | 1220 | is-fullwidth-code-point@^3.0.0: 1221 | version "3.0.0" 1222 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 1223 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 1224 | 1225 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: 1226 | version "4.0.3" 1227 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 1228 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1229 | dependencies: 1230 | is-extglob "^2.1.1" 1231 | 1232 | is-number@^7.0.0: 1233 | version "7.0.0" 1234 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 1235 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1236 | 1237 | is-path-inside@^3.0.3: 1238 | version "3.0.3" 1239 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" 1240 | integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== 1241 | 1242 | is-plain-obj@^2.1.0: 1243 | version "2.1.0" 1244 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 1245 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 1246 | 1247 | is-stream@^2.0.0: 1248 | version "2.0.1" 1249 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" 1250 | integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== 1251 | 1252 | is-typedarray@^1.0.0, is-typedarray@~1.0.0: 1253 | version "1.0.0" 1254 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 1255 | integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== 1256 | 1257 | is-unicode-supported@^0.1.0: 1258 | version "0.1.0" 1259 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 1260 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 1261 | 1262 | is-windows@^1.0.2: 1263 | version "1.0.2" 1264 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" 1265 | integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== 1266 | 1267 | isexe@^2.0.0: 1268 | version "2.0.0" 1269 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 1270 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 1271 | 1272 | isstream@~0.1.2: 1273 | version "0.1.2" 1274 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 1275 | integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== 1276 | 1277 | istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: 1278 | version "3.2.2" 1279 | resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" 1280 | integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== 1281 | 1282 | istanbul-lib-hook@^3.0.0: 1283 | version "3.0.0" 1284 | resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" 1285 | integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== 1286 | dependencies: 1287 | append-transform "^2.0.0" 1288 | 1289 | istanbul-lib-instrument@^4.0.0: 1290 | version "4.0.3" 1291 | resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" 1292 | integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== 1293 | dependencies: 1294 | "@babel/core" "^7.7.5" 1295 | "@istanbuljs/schema" "^0.1.2" 1296 | istanbul-lib-coverage "^3.0.0" 1297 | semver "^6.3.0" 1298 | 1299 | istanbul-lib-processinfo@^2.0.2: 1300 | version "2.0.3" 1301 | resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" 1302 | integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== 1303 | dependencies: 1304 | archy "^1.0.0" 1305 | cross-spawn "^7.0.3" 1306 | istanbul-lib-coverage "^3.2.0" 1307 | p-map "^3.0.0" 1308 | rimraf "^3.0.0" 1309 | uuid "^8.3.2" 1310 | 1311 | istanbul-lib-report@^3.0.0: 1312 | version "3.0.1" 1313 | resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" 1314 | integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== 1315 | dependencies: 1316 | istanbul-lib-coverage "^3.0.0" 1317 | make-dir "^4.0.0" 1318 | supports-color "^7.1.0" 1319 | 1320 | istanbul-lib-source-maps@^4.0.0: 1321 | version "4.0.1" 1322 | resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" 1323 | integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== 1324 | dependencies: 1325 | debug "^4.1.1" 1326 | istanbul-lib-coverage "^3.0.0" 1327 | source-map "^0.6.1" 1328 | 1329 | istanbul-reports@^3.0.2: 1330 | version "3.1.6" 1331 | resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" 1332 | integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== 1333 | dependencies: 1334 | html-escaper "^2.0.0" 1335 | istanbul-lib-report "^3.0.0" 1336 | 1337 | js-tokens@^4.0.0: 1338 | version "4.0.0" 1339 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 1340 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 1341 | 1342 | js-yaml@4.1.0, js-yaml@^4.1.0: 1343 | version "4.1.0" 1344 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 1345 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1346 | dependencies: 1347 | argparse "^2.0.1" 1348 | 1349 | js-yaml@^3.13.1: 1350 | version "3.14.1" 1351 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 1352 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 1353 | dependencies: 1354 | argparse "^1.0.7" 1355 | esprima "^4.0.0" 1356 | 1357 | jsbn@~0.1.0: 1358 | version "0.1.1" 1359 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 1360 | integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== 1361 | 1362 | jsesc@^2.5.1: 1363 | version "2.5.2" 1364 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" 1365 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== 1366 | 1367 | json-buffer@3.0.1: 1368 | version "3.0.1" 1369 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 1370 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 1371 | 1372 | json-schema-traverse@^0.4.1: 1373 | version "0.4.1" 1374 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 1375 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 1376 | 1377 | json-schema@0.4.0: 1378 | version "0.4.0" 1379 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" 1380 | integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== 1381 | 1382 | json-stable-stringify-without-jsonify@^1.0.1: 1383 | version "1.0.1" 1384 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 1385 | integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 1386 | 1387 | json-stringify-safe@~5.0.1: 1388 | version "5.0.1" 1389 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 1390 | integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== 1391 | 1392 | json5@^2.2.3: 1393 | version "2.2.3" 1394 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" 1395 | integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== 1396 | 1397 | jsprim@^1.2.2: 1398 | version "1.4.2" 1399 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" 1400 | integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== 1401 | dependencies: 1402 | assert-plus "1.0.0" 1403 | extsprintf "1.3.0" 1404 | json-schema "0.4.0" 1405 | verror "1.10.0" 1406 | 1407 | keyv@^4.5.3: 1408 | version "4.5.4" 1409 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" 1410 | integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 1411 | dependencies: 1412 | json-buffer "3.0.1" 1413 | 1414 | lcov-parse@^1.0.0: 1415 | version "1.0.0" 1416 | resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" 1417 | integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== 1418 | 1419 | levn@^0.4.1: 1420 | version "0.4.1" 1421 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 1422 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 1423 | dependencies: 1424 | prelude-ls "^1.2.1" 1425 | type-check "~0.4.0" 1426 | 1427 | libsodium-wrappers@^0.5.2: 1428 | version "0.5.4" 1429 | resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.5.4.tgz#0059bf219c3a37b228f823342399b1607a4c5ba4" 1430 | integrity sha512-dAYsfQgh6XwR4I65y7T5qDgb2XNKDpzXEXz229sDplaJfnAuIBTHBYlQ44jL5DIS4cCUspE3+g0kF4/Xe8286A== 1431 | dependencies: 1432 | libsodium "0.5.4" 1433 | 1434 | libsodium@0.5.4: 1435 | version "0.5.4" 1436 | resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.5.4.tgz#874413435ee40c512dd59ea6db9b75970f8aec02" 1437 | integrity sha512-s1TQ2V23JvGby1gnCQEQncTNTGck/rtJPPA8c0TiBo9z9TpT4eUk5zThte8H1TkdoKQznneqZqyoqdrwu2btWw== 1438 | 1439 | locate-path@^5.0.0: 1440 | version "5.0.0" 1441 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 1442 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 1443 | dependencies: 1444 | p-locate "^4.1.0" 1445 | 1446 | locate-path@^6.0.0: 1447 | version "6.0.0" 1448 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 1449 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1450 | dependencies: 1451 | p-locate "^5.0.0" 1452 | 1453 | lodash.flattendeep@^4.4.0: 1454 | version "4.4.0" 1455 | resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" 1456 | integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== 1457 | 1458 | lodash.merge@^4.6.2: 1459 | version "4.6.2" 1460 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 1461 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 1462 | 1463 | log-driver@^1.2.7: 1464 | version "1.2.7" 1465 | resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" 1466 | integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== 1467 | 1468 | log-symbols@4.1.0: 1469 | version "4.1.0" 1470 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 1471 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 1472 | dependencies: 1473 | chalk "^4.1.0" 1474 | is-unicode-supported "^0.1.0" 1475 | 1476 | loupe@^2.3.6: 1477 | version "2.3.7" 1478 | resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" 1479 | integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== 1480 | dependencies: 1481 | get-func-name "^2.0.1" 1482 | 1483 | lru-cache@^5.1.1: 1484 | version "5.1.1" 1485 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" 1486 | integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== 1487 | dependencies: 1488 | yallist "^3.0.2" 1489 | 1490 | lru-cache@^6.0.0: 1491 | version "6.0.0" 1492 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 1493 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 1494 | dependencies: 1495 | yallist "^4.0.0" 1496 | 1497 | make-dir@^3.0.0, make-dir@^3.0.2: 1498 | version "3.1.0" 1499 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" 1500 | integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== 1501 | dependencies: 1502 | semver "^6.0.0" 1503 | 1504 | make-dir@^4.0.0: 1505 | version "4.0.0" 1506 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" 1507 | integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== 1508 | dependencies: 1509 | semver "^7.5.3" 1510 | 1511 | mime-db@1.52.0: 1512 | version "1.52.0" 1513 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1514 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1515 | 1516 | mime-types@^2.1.12, mime-types@~2.1.19: 1517 | version "2.1.35" 1518 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1519 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1520 | dependencies: 1521 | mime-db "1.52.0" 1522 | 1523 | minimatch@5.0.1: 1524 | version "5.0.1" 1525 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" 1526 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== 1527 | dependencies: 1528 | brace-expansion "^2.0.1" 1529 | 1530 | minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: 1531 | version "3.1.2" 1532 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1533 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1534 | dependencies: 1535 | brace-expansion "^1.1.7" 1536 | 1537 | minimist@^1.2.5: 1538 | version "1.2.8" 1539 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 1540 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 1541 | 1542 | mocha@^10.2.0: 1543 | version "10.2.0" 1544 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" 1545 | integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== 1546 | dependencies: 1547 | ansi-colors "4.1.1" 1548 | browser-stdout "1.3.1" 1549 | chokidar "3.5.3" 1550 | debug "4.3.4" 1551 | diff "5.0.0" 1552 | escape-string-regexp "4.0.0" 1553 | find-up "5.0.0" 1554 | glob "7.2.0" 1555 | he "1.2.0" 1556 | js-yaml "4.1.0" 1557 | log-symbols "4.1.0" 1558 | minimatch "5.0.1" 1559 | ms "2.1.3" 1560 | nanoid "3.3.3" 1561 | serialize-javascript "6.0.0" 1562 | strip-json-comments "3.1.1" 1563 | supports-color "8.1.1" 1564 | workerpool "6.2.1" 1565 | yargs "16.2.0" 1566 | yargs-parser "20.2.4" 1567 | yargs-unparser "2.0.0" 1568 | 1569 | ms@2.1.2: 1570 | version "2.1.2" 1571 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1572 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1573 | 1574 | ms@2.1.3: 1575 | version "2.1.3" 1576 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1577 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1578 | 1579 | nanoid@3.3.3: 1580 | version "3.3.3" 1581 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" 1582 | integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== 1583 | 1584 | natural-compare@^1.4.0: 1585 | version "1.4.0" 1586 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 1587 | integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 1588 | 1589 | node-preload@^0.2.1: 1590 | version "0.2.1" 1591 | resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" 1592 | integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== 1593 | dependencies: 1594 | process-on-spawn "^1.0.0" 1595 | 1596 | node-releases@^2.0.14: 1597 | version "2.0.14" 1598 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" 1599 | integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== 1600 | 1601 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1602 | version "3.0.0" 1603 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1604 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1605 | 1606 | nyc@^15.1.0: 1607 | version "15.1.0" 1608 | resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" 1609 | integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== 1610 | dependencies: 1611 | "@istanbuljs/load-nyc-config" "^1.0.0" 1612 | "@istanbuljs/schema" "^0.1.2" 1613 | caching-transform "^4.0.0" 1614 | convert-source-map "^1.7.0" 1615 | decamelize "^1.2.0" 1616 | find-cache-dir "^3.2.0" 1617 | find-up "^4.1.0" 1618 | foreground-child "^2.0.0" 1619 | get-package-type "^0.1.0" 1620 | glob "^7.1.6" 1621 | istanbul-lib-coverage "^3.0.0" 1622 | istanbul-lib-hook "^3.0.0" 1623 | istanbul-lib-instrument "^4.0.0" 1624 | istanbul-lib-processinfo "^2.0.2" 1625 | istanbul-lib-report "^3.0.0" 1626 | istanbul-lib-source-maps "^4.0.0" 1627 | istanbul-reports "^3.0.2" 1628 | make-dir "^3.0.0" 1629 | node-preload "^0.2.1" 1630 | p-map "^3.0.0" 1631 | process-on-spawn "^1.0.0" 1632 | resolve-from "^5.0.0" 1633 | rimraf "^3.0.0" 1634 | signal-exit "^3.0.2" 1635 | spawn-wrap "^2.0.0" 1636 | test-exclude "^6.0.0" 1637 | yargs "^15.0.2" 1638 | 1639 | oauth-sign@~0.9.0: 1640 | version "0.9.0" 1641 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 1642 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== 1643 | 1644 | once@^1.3.0: 1645 | version "1.4.0" 1646 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1647 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1648 | dependencies: 1649 | wrappy "1" 1650 | 1651 | optionator@^0.9.3: 1652 | version "0.9.3" 1653 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" 1654 | integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== 1655 | dependencies: 1656 | "@aashutoshrathi/word-wrap" "^1.2.3" 1657 | deep-is "^0.1.3" 1658 | fast-levenshtein "^2.0.6" 1659 | levn "^0.4.1" 1660 | prelude-ls "^1.2.1" 1661 | type-check "^0.4.0" 1662 | 1663 | p-limit@^2.2.0: 1664 | version "2.3.0" 1665 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1666 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 1667 | dependencies: 1668 | p-try "^2.0.0" 1669 | 1670 | p-limit@^3.0.2: 1671 | version "3.1.0" 1672 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1673 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1674 | dependencies: 1675 | yocto-queue "^0.1.0" 1676 | 1677 | p-locate@^4.1.0: 1678 | version "4.1.0" 1679 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1680 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1681 | dependencies: 1682 | p-limit "^2.2.0" 1683 | 1684 | p-locate@^5.0.0: 1685 | version "5.0.0" 1686 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1687 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1688 | dependencies: 1689 | p-limit "^3.0.2" 1690 | 1691 | p-map@^3.0.0: 1692 | version "3.0.0" 1693 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" 1694 | integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== 1695 | dependencies: 1696 | aggregate-error "^3.0.0" 1697 | 1698 | p-try@^2.0.0: 1699 | version "2.2.0" 1700 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1701 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 1702 | 1703 | package-hash@^4.0.0: 1704 | version "4.0.0" 1705 | resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" 1706 | integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== 1707 | dependencies: 1708 | graceful-fs "^4.1.15" 1709 | hasha "^5.0.0" 1710 | lodash.flattendeep "^4.4.0" 1711 | release-zalgo "^1.0.0" 1712 | 1713 | parent-module@^1.0.0: 1714 | version "1.0.1" 1715 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1716 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1717 | dependencies: 1718 | callsites "^3.0.0" 1719 | 1720 | path-exists@^4.0.0: 1721 | version "4.0.0" 1722 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1723 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1724 | 1725 | path-is-absolute@^1.0.0: 1726 | version "1.0.1" 1727 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1728 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1729 | 1730 | path-key@^3.1.0: 1731 | version "3.1.1" 1732 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1733 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1734 | 1735 | pathval@^1.1.1: 1736 | version "1.1.1" 1737 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" 1738 | integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== 1739 | 1740 | performance-now@^2.1.0: 1741 | version "2.1.0" 1742 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 1743 | integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== 1744 | 1745 | picocolors@^1.0.0: 1746 | version "1.0.0" 1747 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 1748 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1749 | 1750 | picomatch@^2.0.4, picomatch@^2.2.1: 1751 | version "2.3.1" 1752 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1753 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1754 | 1755 | pkg-dir@^4.1.0: 1756 | version "4.2.0" 1757 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1758 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1759 | dependencies: 1760 | find-up "^4.0.0" 1761 | 1762 | pkginfo@^0.4.1: 1763 | version "0.4.1" 1764 | resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" 1765 | integrity sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ== 1766 | 1767 | prelude-ls@^1.2.1: 1768 | version "1.2.1" 1769 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 1770 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 1771 | 1772 | prettier@^3.1.1: 1773 | version "3.1.1" 1774 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" 1775 | integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== 1776 | 1777 | process-on-spawn@^1.0.0: 1778 | version "1.0.0" 1779 | resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" 1780 | integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== 1781 | dependencies: 1782 | fromentries "^1.2.0" 1783 | 1784 | psl@^1.1.28: 1785 | version "1.9.0" 1786 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" 1787 | integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== 1788 | 1789 | punycode@^2.1.0, punycode@^2.1.1: 1790 | version "2.3.1" 1791 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 1792 | integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 1793 | 1794 | qs@~6.5.2: 1795 | version "6.5.3" 1796 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" 1797 | integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== 1798 | 1799 | queue-microtask@^1.2.2: 1800 | version "1.2.3" 1801 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 1802 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 1803 | 1804 | randombytes@^2.1.0: 1805 | version "2.1.0" 1806 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1807 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1808 | dependencies: 1809 | safe-buffer "^5.1.0" 1810 | 1811 | readdirp@~3.6.0: 1812 | version "3.6.0" 1813 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1814 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1815 | dependencies: 1816 | picomatch "^2.2.1" 1817 | 1818 | release-zalgo@^1.0.0: 1819 | version "1.0.0" 1820 | resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" 1821 | integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== 1822 | dependencies: 1823 | es6-error "^4.0.1" 1824 | 1825 | request@^2.88.2: 1826 | version "2.88.2" 1827 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" 1828 | integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== 1829 | dependencies: 1830 | aws-sign2 "~0.7.0" 1831 | aws4 "^1.8.0" 1832 | caseless "~0.12.0" 1833 | combined-stream "~1.0.6" 1834 | extend "~3.0.2" 1835 | forever-agent "~0.6.1" 1836 | form-data "~2.3.2" 1837 | har-validator "~5.1.3" 1838 | http-signature "~1.2.0" 1839 | is-typedarray "~1.0.0" 1840 | isstream "~0.1.2" 1841 | json-stringify-safe "~5.0.1" 1842 | mime-types "~2.1.19" 1843 | oauth-sign "~0.9.0" 1844 | performance-now "^2.1.0" 1845 | qs "~6.5.2" 1846 | safe-buffer "^5.1.2" 1847 | tough-cookie "~2.5.0" 1848 | tunnel-agent "^0.6.0" 1849 | uuid "^3.3.2" 1850 | 1851 | require-directory@^2.1.1: 1852 | version "2.1.1" 1853 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1854 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 1855 | 1856 | require-main-filename@^2.0.0: 1857 | version "2.0.0" 1858 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 1859 | integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== 1860 | 1861 | resolve-from@^4.0.0: 1862 | version "4.0.0" 1863 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1864 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1865 | 1866 | resolve-from@^5.0.0: 1867 | version "5.0.0" 1868 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 1869 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 1870 | 1871 | reusify@^1.0.4: 1872 | version "1.0.4" 1873 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 1874 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1875 | 1876 | rimraf@^3.0.0, rimraf@^3.0.2: 1877 | version "3.0.2" 1878 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1879 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1880 | dependencies: 1881 | glob "^7.1.3" 1882 | 1883 | run-parallel@^1.1.9: 1884 | version "1.2.0" 1885 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 1886 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1887 | dependencies: 1888 | queue-microtask "^1.2.2" 1889 | 1890 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: 1891 | version "5.2.1" 1892 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1893 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1894 | 1895 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 1896 | version "2.1.2" 1897 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1898 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1899 | 1900 | semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: 1901 | version "6.3.1" 1902 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" 1903 | integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== 1904 | 1905 | semver@^7.5.3: 1906 | version "7.5.4" 1907 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" 1908 | integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== 1909 | dependencies: 1910 | lru-cache "^6.0.0" 1911 | 1912 | serialize-javascript@6.0.0: 1913 | version "6.0.0" 1914 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 1915 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 1916 | dependencies: 1917 | randombytes "^2.1.0" 1918 | 1919 | set-blocking@^2.0.0: 1920 | version "2.0.0" 1921 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1922 | integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== 1923 | 1924 | shebang-command@^2.0.0: 1925 | version "2.0.0" 1926 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1927 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1928 | dependencies: 1929 | shebang-regex "^3.0.0" 1930 | 1931 | shebang-regex@^3.0.0: 1932 | version "3.0.0" 1933 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1934 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1935 | 1936 | signal-exit@^3.0.2: 1937 | version "3.0.7" 1938 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 1939 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 1940 | 1941 | source-map@^0.6.1: 1942 | version "0.6.1" 1943 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1944 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1945 | 1946 | spawn-wrap@^2.0.0: 1947 | version "2.0.0" 1948 | resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" 1949 | integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== 1950 | dependencies: 1951 | foreground-child "^2.0.0" 1952 | is-windows "^1.0.2" 1953 | make-dir "^3.0.0" 1954 | rimraf "^3.0.0" 1955 | signal-exit "^3.0.2" 1956 | which "^2.0.1" 1957 | 1958 | sprintf-js@~1.0.2: 1959 | version "1.0.3" 1960 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1961 | integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== 1962 | 1963 | sshpk@^1.7.0: 1964 | version "1.18.0" 1965 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" 1966 | integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== 1967 | dependencies: 1968 | asn1 "~0.2.3" 1969 | assert-plus "^1.0.0" 1970 | bcrypt-pbkdf "^1.0.0" 1971 | dashdash "^1.12.0" 1972 | ecc-jsbn "~0.1.1" 1973 | getpass "^0.1.1" 1974 | jsbn "~0.1.0" 1975 | safer-buffer "^2.0.2" 1976 | tweetnacl "~0.14.0" 1977 | 1978 | string-width@^4.1.0, string-width@^4.2.0: 1979 | version "4.2.3" 1980 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1981 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1982 | dependencies: 1983 | emoji-regex "^8.0.0" 1984 | is-fullwidth-code-point "^3.0.0" 1985 | strip-ansi "^6.0.1" 1986 | 1987 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1988 | version "6.0.1" 1989 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1990 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1991 | dependencies: 1992 | ansi-regex "^5.0.1" 1993 | 1994 | strip-bom@^4.0.0: 1995 | version "4.0.0" 1996 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" 1997 | integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== 1998 | 1999 | strip-json-comments@3.1.1, strip-json-comments@^3.1.1: 2000 | version "3.1.1" 2001 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 2002 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 2003 | 2004 | supports-color@8.1.1: 2005 | version "8.1.1" 2006 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 2007 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 2008 | dependencies: 2009 | has-flag "^4.0.0" 2010 | 2011 | supports-color@^5.3.0: 2012 | version "5.5.0" 2013 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 2014 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 2015 | dependencies: 2016 | has-flag "^3.0.0" 2017 | 2018 | supports-color@^7.1.0: 2019 | version "7.2.0" 2020 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 2021 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 2022 | dependencies: 2023 | has-flag "^4.0.0" 2024 | 2025 | test-exclude@^6.0.0: 2026 | version "6.0.0" 2027 | resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" 2028 | integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== 2029 | dependencies: 2030 | "@istanbuljs/schema" "^0.1.2" 2031 | glob "^7.1.4" 2032 | minimatch "^3.0.4" 2033 | 2034 | text-table@^0.2.0: 2035 | version "0.2.0" 2036 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 2037 | integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== 2038 | 2039 | tmp@^0.2.1: 2040 | version "0.2.1" 2041 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" 2042 | integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== 2043 | dependencies: 2044 | rimraf "^3.0.0" 2045 | 2046 | to-fast-properties@^2.0.0: 2047 | version "2.0.0" 2048 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 2049 | integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== 2050 | 2051 | to-regex-range@^5.0.1: 2052 | version "5.0.1" 2053 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 2054 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 2055 | dependencies: 2056 | is-number "^7.0.0" 2057 | 2058 | tough-cookie@~2.5.0: 2059 | version "2.5.0" 2060 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 2061 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== 2062 | dependencies: 2063 | psl "^1.1.28" 2064 | punycode "^2.1.1" 2065 | 2066 | tunnel-agent@^0.6.0: 2067 | version "0.6.0" 2068 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 2069 | integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== 2070 | dependencies: 2071 | safe-buffer "^5.0.1" 2072 | 2073 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 2074 | version "0.14.5" 2075 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 2076 | integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== 2077 | 2078 | type-check@^0.4.0, type-check@~0.4.0: 2079 | version "0.4.0" 2080 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 2081 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 2082 | dependencies: 2083 | prelude-ls "^1.2.1" 2084 | 2085 | type-detect@^4.0.0, type-detect@^4.0.8: 2086 | version "4.0.8" 2087 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" 2088 | integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== 2089 | 2090 | type-fest@^0.20.2: 2091 | version "0.20.2" 2092 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" 2093 | integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 2094 | 2095 | type-fest@^0.8.0: 2096 | version "0.8.1" 2097 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 2098 | integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 2099 | 2100 | typedarray-to-buffer@^3.1.5: 2101 | version "3.1.5" 2102 | resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" 2103 | integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== 2104 | dependencies: 2105 | is-typedarray "^1.0.0" 2106 | 2107 | update-browserslist-db@^1.0.13: 2108 | version "1.0.13" 2109 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" 2110 | integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== 2111 | dependencies: 2112 | escalade "^3.1.1" 2113 | picocolors "^1.0.0" 2114 | 2115 | uri-js@^4.2.2: 2116 | version "4.4.1" 2117 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 2118 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 2119 | dependencies: 2120 | punycode "^2.1.0" 2121 | 2122 | urlsafe-base64@1.0.0, urlsafe-base64@^1.0.0: 2123 | version "1.0.0" 2124 | resolved "https://registry.yarnpkg.com/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz#23f89069a6c62f46cf3a1d3b00169cefb90be0c6" 2125 | integrity sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA== 2126 | 2127 | uuid@^3.3.2: 2128 | version "3.4.0" 2129 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 2130 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 2131 | 2132 | uuid@^8.3.2: 2133 | version "8.3.2" 2134 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" 2135 | integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== 2136 | 2137 | verror@1.10.0: 2138 | version "1.10.0" 2139 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 2140 | integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== 2141 | dependencies: 2142 | assert-plus "^1.0.0" 2143 | core-util-is "1.0.2" 2144 | extsprintf "^1.2.0" 2145 | 2146 | which-module@^2.0.0: 2147 | version "2.0.1" 2148 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" 2149 | integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== 2150 | 2151 | which@^2.0.1: 2152 | version "2.0.2" 2153 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 2154 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 2155 | dependencies: 2156 | isexe "^2.0.0" 2157 | 2158 | workerpool@6.2.1: 2159 | version "6.2.1" 2160 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" 2161 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== 2162 | 2163 | wrap-ansi@^6.2.0: 2164 | version "6.2.0" 2165 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 2166 | integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== 2167 | dependencies: 2168 | ansi-styles "^4.0.0" 2169 | string-width "^4.1.0" 2170 | strip-ansi "^6.0.0" 2171 | 2172 | wrap-ansi@^7.0.0: 2173 | version "7.0.0" 2174 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 2175 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 2176 | dependencies: 2177 | ansi-styles "^4.0.0" 2178 | string-width "^4.1.0" 2179 | strip-ansi "^6.0.0" 2180 | 2181 | wrappy@1: 2182 | version "1.0.2" 2183 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 2184 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 2185 | 2186 | write-file-atomic@^3.0.0: 2187 | version "3.0.3" 2188 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" 2189 | integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== 2190 | dependencies: 2191 | imurmurhash "^0.1.4" 2192 | is-typedarray "^1.0.0" 2193 | signal-exit "^3.0.2" 2194 | typedarray-to-buffer "^3.1.5" 2195 | 2196 | y18n@^4.0.0: 2197 | version "4.0.3" 2198 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" 2199 | integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== 2200 | 2201 | y18n@^5.0.5: 2202 | version "5.0.8" 2203 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 2204 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 2205 | 2206 | yallist@^3.0.2: 2207 | version "3.1.1" 2208 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" 2209 | integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 2210 | 2211 | yallist@^4.0.0: 2212 | version "4.0.0" 2213 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 2214 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 2215 | 2216 | yargs-parser@20.2.4: 2217 | version "20.2.4" 2218 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 2219 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 2220 | 2221 | yargs-parser@^18.1.2: 2222 | version "18.1.3" 2223 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" 2224 | integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== 2225 | dependencies: 2226 | camelcase "^5.0.0" 2227 | decamelize "^1.2.0" 2228 | 2229 | yargs-parser@^20.2.2: 2230 | version "20.2.9" 2231 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 2232 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 2233 | 2234 | yargs-unparser@2.0.0: 2235 | version "2.0.0" 2236 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 2237 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 2238 | dependencies: 2239 | camelcase "^6.0.0" 2240 | decamelize "^4.0.0" 2241 | flat "^5.0.2" 2242 | is-plain-obj "^2.1.0" 2243 | 2244 | yargs@16.2.0: 2245 | version "16.2.0" 2246 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 2247 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 2248 | dependencies: 2249 | cliui "^7.0.2" 2250 | escalade "^3.1.1" 2251 | get-caller-file "^2.0.5" 2252 | require-directory "^2.1.1" 2253 | string-width "^4.2.0" 2254 | y18n "^5.0.5" 2255 | yargs-parser "^20.2.2" 2256 | 2257 | yargs@^15.0.2: 2258 | version "15.4.1" 2259 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" 2260 | integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== 2261 | dependencies: 2262 | cliui "^6.0.0" 2263 | decamelize "^1.2.0" 2264 | find-up "^4.1.0" 2265 | get-caller-file "^2.0.1" 2266 | require-directory "^2.1.1" 2267 | require-main-filename "^2.0.0" 2268 | set-blocking "^2.0.0" 2269 | string-width "^4.2.0" 2270 | which-module "^2.0.0" 2271 | y18n "^4.0.0" 2272 | yargs-parser "^18.1.2" 2273 | 2274 | yocto-queue@^0.1.0: 2275 | version "0.1.0" 2276 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 2277 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 2278 | --------------------------------------------------------------------------------