From a846beef48a8966309bb4d98adea4e5c1c17e379 Mon Sep 17 00:00:00 2001 From: Gonzalo Date: Fri, 1 Sep 2023 14:48:14 -0400 Subject: [PATCH] v0.3.0 (#164) * feat: Add minimal fe support * fix: fix tests for fe module * chore: fmt * chore: attempt to install fe on workflow * fix: add url to curl command * fix: fix curl command * Invariant testing base contract * Complete invariants module and add bound function from forge-std * forge fmt * chore: use fe v0.24.0 * docs: add docs for the `Fe` module. * chore: export `fe` from `script.sol` * chore: export `Fe` struct from `script.sol` * chore: export huff from script.sol * fix: fix Fe module import on script.sol * feat: add method to create multiple addresses * chore: rename method * empty * Add invariant functions that receive arrays * Add docs * Add docs * Format * Fix docs * fix: fix Fe module documentation * fix: json safe create and improve accounts * feat: use tryFfi on commands (#136) * feat: use tryFfi on commands * style: fmt * feat: use CommandResult instead of FfiResult * chore: remove Hevm copy and replace with ad hoc interface * chore: extend CommandResult * chore: update function names * chore: use unwrap/expect as function names * style: fmt * test: improve unwrap test * style: fmt * docs: update commands docs (#142) * docs: update commands docs * docs: add expect example * chore: remove console unused imports * chore: update unwrap error format (#145) * chore: make output dir optional when building Fe code (#149) * chore: add `rawConsoleLog` function (#152) * feat: add `rawConsoleLog` function Add a `rawConsoleLog` function to prevent compiling the whole `console` contract from `forge-std`. Resolves #120 * chore: use println instead of rawConsoleLog * feat: adds createMay(length, prefix) (#150) Adds a new function to the `accounts` module `createMany(length, prefix)` that creates an array of addresses of a specified length and applies a label to each one with a prefix `prefix` in the form of `{prefix}_{i}`. * chore: add formatError function (#153) * chore: add `formatError` function add `formatError` function to standardize Vulcan error messages. Resolves #105 * chore: add formatError to accounts * chore: progress adding formatError to modules * chore: add formatError to fmt * chore: add formatError to missing modules * chore: update forge-std to commit 1d9650e (#157) * chore: remove TryFfi interface (#159) Removes the `TryFfi` interface and uses the `forge-std` `Vm` `tryFfi` method directly. * docs: update vulcan version to 0.3.0 * docs: update installation guide vulcan version * chore(main): release 0.3.0 * chore: setup husky and commitlint (#161) --------- Co-authored-by: Vicente Dragicevic Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 7 +- .gitignore | 6 + .husky/commit-msg | 4 + CHANGELOG.md | 16 + README.md | 2 +- commitlint.config.js | 1 + docs/src/SUMMARY.md | 3 + docs/src/guide/installation.md | 2 +- docs/src/modules/commands.md | 18 +- docs/src/modules/fe.md | 25 + docs/src/reference/modules/commands.md | 65 +- docs/src/reference/modules/fe.md | 45 + docs/src/reference/modules/invariants.md | 73 + docs/src/testing/README.md | 23 +- foundry.toml | 3 +- lib/forge-std | 2 +- package-lock.json | 2253 ++++++++++++++++++++++ package.json | 17 + src/_modules/Accounts.sol | 61 + src/_modules/Commands.sol | 97 +- src/_modules/Config.sol | 3 +- src/_modules/Context.sol | 9 +- src/_modules/Fe.sol | 98 + src/_modules/Fmt.sol | 14 +- src/_modules/Fs.sol | 1 - src/_modules/Gas.sol | 7 +- src/_modules/Huff.sol | 13 +- src/_modules/Invariants.sol | 195 ++ src/_modules/Json.sol | 16 +- src/_modules/Watchers.sol | 10 +- src/_utils/bound.sol | 57 + src/_utils/formatError.sol | 6 + src/_utils/println.sol | 10 +- src/_utils/rawConsole.sol | 8 + src/script.sol | 5 +- src/test.sol | 10 +- test/ExampleTest.sol | 6 +- test/_modules/Accounts.t.sol | 19 + test/_modules/Commands.t.sol | 56 +- test/_modules/Fe.t.sol | 55 + test/_modules/Forks.t.sol | 8 +- test/_modules/Huff.t.sol | 6 +- test/mocks/guest_book.fe | 3 + 43 files changed, 3234 insertions(+), 104 deletions(-) create mode 100755 .husky/commit-msg create mode 100644 CHANGELOG.md create mode 100644 commitlint.config.js create mode 100644 docs/src/modules/fe.md create mode 100644 docs/src/reference/modules/fe.md create mode 100644 docs/src/reference/modules/invariants.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/_modules/Fe.sol create mode 100644 src/_modules/Invariants.sol create mode 100644 src/_utils/bound.sol create mode 100644 src/_utils/formatError.sol create mode 100644 src/_utils/rawConsole.sol create mode 100644 test/_modules/Fe.t.sol create mode 100644 test/mocks/guest_book.fe diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a9891804..0f0ada6a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,6 +28,11 @@ jobs: with: version: nightly + - name: Install Fe + run: | + curl -L https://github.com/ethereum/fe/releases/download/v0.24.0/fe_amd64 -o /usr/local/bin/fe -s + chmod +x /usr/local/bin/fe + - name: Run Forge build run: | forge --version @@ -52,4 +57,4 @@ jobs: run: forge --version - name: Check formatting - run: forge fmt --check \ No newline at end of file + run: forge fmt --check diff --git a/.gitignore b/.gitignore index e7931471..c0dda2d7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,9 @@ out/ .env .DS_Store + +# Test stuff +test/fixtures/fe + +# Node stuff +node_modules diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000..c160a771 --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npx --no -- commitlint --edit ${1} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..7996228f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## [0.3.0](https://github.com/nomoixyz/vulcan/compare/v0.2.0...v0.3.0) (2023-09-01) + + +### Features + +* add function to create empty command ([2c31886](https://github.com/nomoixyz/vulcan/commit/2c31886075fae5a5177410739309ff38ed834f2a)) +* export Command struct from script.sol ([c88883a](https://github.com/nomoixyz/vulcan/commit/c88883a402ccfae6aa2d0de674936ba22e3d3514)) + + +### Bug Fixes + +* fix return natspect documentation ([5da4ad1](https://github.com/nomoixyz/vulcan/commit/5da4ad14fbe07b35d29260fe2cb97ffb2cb95de3)) +* tabs ([1d4c0b9](https://github.com/nomoixyz/vulcan/commit/1d4c0b9d350445825d84198c7b242f5e432ffb39)) +* update code examples ([953d661](https://github.com/nomoixyz/vulcan/commit/953d661e1a84e84b9a40b8f8178980ea32d0ef96)) diff --git a/README.md b/README.md index 3f0a5190..b45f7213 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Over time, Vulcan will grow to include more functionality and utilities, eventua ## Installation ``` -$ forge install nomoixyz/vulcan@v0.2.0 +$ forge install nomoixyz/vulcan@v0.3.0 ``` ## Usage diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..28fe5c5b --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = {extends: ['@commitlint/config-conventional']} diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d3e79c2f..4c037b1a 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -14,6 +14,7 @@ - [Context](./modules/context.md) - [Env](./modules/env.md) - [Events](./modules/events.md) + - [Fe](./modules/fe.md) - [Format](./modules/fmt.md) - [Forks](./modules/forks.md) - [Fs](./modules/fs.md) @@ -32,10 +33,12 @@ - [Context](./reference/modules/context.md) - [Env](./reference/modules/env.md) - [Events](./reference/modules/events.md) + - [Fe](./reference/modules/fe.md) - [Format](./reference/modules/fmt.md) - [Forks](./reference/modules/forks.md) - [Fs](./reference/modules/fs.md) - [Huff](./reference/modules/huff.md) + - [Invariants](./reference/modules/invariants.md) - [Json](./reference/modules/json.md) - [Strings](./reference/modules/strings.md) - [Watchers](./reference/modules/watchers.md) diff --git a/docs/src/guide/installation.md b/docs/src/guide/installation.md index 7e930118..424a53b6 100644 --- a/docs/src/guide/installation.md +++ b/docs/src/guide/installation.md @@ -2,5 +2,5 @@ In an existing Foundry project, use `forge install`: ``` -$ forge install nomoixyz/vulcan@0.1.0 +$ forge install nomoixyz/vulcan@0.3.0 ``` diff --git a/docs/src/modules/commands.md b/docs/src/modules/commands.md index d7dbcea5..94222e1c 100644 --- a/docs/src/modules/commands.md +++ b/docs/src/modules/commands.md @@ -4,7 +4,7 @@ Execute external commands. The `ffi` setting must be enabled on `foundry.toml` f work. ```solidity -import { Test, Command, commands } from "vulcan/test.sol"; +import { Test, Command, commands, CommandResult } from "vulcan/test.sol"; contract TestMyContract is Test { using commands for *; @@ -12,7 +12,21 @@ contract TestMyContract is Test { function testMyContract() external { // run `echo Hello World`. // There is no need to create a dynamic array for the arguments - bytes memory res = commands.run(["echo", "Hello World"]); + CommandResult memory res = commands.run(["echo", "Hello World"]); + + if (res.isOk()) { + // do something + } + + if (res.isError()) { + // do something else + } + + // This will return the output from `stdout` or revert if the command failed. + bytes memory output = res.unwrap(); + + // or provide a custom error message in case the command execution fails. + output = res.expect("Somehow echo failed"); // A comand can be created to facilitate multiple executions Command memory cmd = commands.create("echo").arg("Hello World"); diff --git a/docs/src/modules/fe.md b/docs/src/modules/fe.md new file mode 100644 index 00000000..8a35e6b5 --- /dev/null +++ b/docs/src/modules/fe.md @@ -0,0 +1,25 @@ +# Fe + +Provides [Fe](https://fe-lang.org/) compiler support. The `ffi` setting must be enabled on `foundry.toml` for this module +to work. + +```solidity +import { Test, fe } from "vulcan/test.sol"; + +contract TestMyContract is Test { + function testCompile() external { + fe + .create() + .setFilePath("./test/mocks/guest_book.fe") + .setOutputDir("./test/fixtures/fe/output") + .setOverwrite(true) + .build() + .unwrap(); + + bytes memory bytecode = fe.getBytecode("GuestBook"); + } + +} +``` +[**Fe API reference**](../reference/modules/fe.md) + diff --git a/docs/src/reference/modules/commands.md b/docs/src/reference/modules/commands.md index 353b4bdc..d219f183 100644 --- a/docs/src/reference/modules/commands.md +++ b/docs/src/reference/modules/commands.md @@ -74,69 +74,86 @@ Creates a new `Command` struct using the provided `input` as the executable. #### **`args(Command self, string[20] _args) → (Command)`** -#### **`run(Command self) → (bytes)`** +#### **`run(Command self) → (CommandResult)`** -Runs a command using the specified `Command` struct as parameters and returns the result. +Runs a command using the specified `Command` struct as parameters and returns a `CommandResult` +struct. -#### **`run(string[] inputs) → (bytes)`** +#### **`run(string[] inputs) → (CommandResult)`** -Runs a command with the specified `inputs` as parameters and returns the result. +Runs a command with the specified `inputs` as parameters and returns a `CommandResult` struct. -#### **`run(string[1] inputs) → (bytes)`** +#### **`isOk(CommandResult self) → (bool)`** +Returns `true` if the command ran successfully and `false` otherwise. -#### **`run(string[2] inputs) → (bytes)`** +#### **`isError(CommandResult self) → (bool)`** +Returns `true` if the command failed and `false` otherwise. -#### **`run(string[3] inputs) → (bytes)`** +#### **`unwrap(CommandResult self) → (bytes)`** +Returns the output from `stdout` or reverts if the command failed to run. -#### **`run(string[4] inputs) → (bytes)`** +#### **`expect(CommandResult self, string customError) → (bytes)`** +Returns the output from `stdout` or reverts with `customError` if the command failed to run. -#### **`run(string[5] inputs) → (bytes)`** +#### **`run(string[1] inputs) → (CommandResult)`** -#### **`run(string[6] inputs) → (bytes)`** +#### **`run(string[2] inputs) → (CommandResult)`** -#### **`run(string[7] inputs) → (bytes)`** +#### **`run(string[3] inputs) → (CommandResult)`** -#### **`run(string[8] inputs) → (bytes)`** +#### **`run(string[4] inputs) → (CommandResult)`** -#### **`run(string[9] inputs) → (bytes)`** +#### **`run(string[5] inputs) → (CommandResult)`** -#### **`run(string[10] inputs) → (bytes)`** +#### **`run(string[6] inputs) → (CommandResult)`** -#### **`run(string[11] inputs) → (bytes)`** +#### **`run(string[7] inputs) → (CommandResult)`** -#### **`run(string[12] inputs) → (bytes)`** +#### **`run(string[8] inputs) → (CommandResult)`** -#### **`run(string[13] inputs) → (bytes)`** +#### **`run(string[9] inputs) → (CommandResult)`** -#### **`run(string[14] inputs) → (bytes)`** +#### **`run(string[10] inputs) → (CommandResult)`** -#### **`run(string[15] inputs) → (bytes)`** +#### **`run(string[11] inputs) → (CommandResult)`** -#### **`run(string[16] inputs) → (bytes)`** +#### **`run(string[12] inputs) → (CommandResult)`** -#### **`run(string[17] inputs) → (bytes)`** +#### **`run(string[13] inputs) → (CommandResult)`** -#### **`run(string[18] inputs) → (bytes)`** +#### **`run(string[14] inputs) → (CommandResult)`** -#### **`run(string[19] inputs) → (bytes)`** +#### **`run(string[15] inputs) → (CommandResult)`** -#### **`run(string[20] inputs) → (bytes)`** +#### **`run(string[16] inputs) → (CommandResult)`** + + +#### **`run(string[17] inputs) → (CommandResult)`** + + +#### **`run(string[18] inputs) → (CommandResult)`** + + +#### **`run(string[19] inputs) → (CommandResult)`** + + +#### **`run(string[20] inputs) → (CommandResult)`** diff --git a/docs/src/reference/modules/fe.md b/docs/src/reference/modules/fe.md new file mode 100644 index 00000000..c3cb9148 --- /dev/null +++ b/docs/src/reference/modules/fe.md @@ -0,0 +1,45 @@ +# Fe + +#### **`create() → (Fe)`** + +Creates a new `Fe` struct with the following defaults. + +```solidity +Fe({ + compilerPath: "fe", + filePath: "", + outputDir: "", + overwrite: false +}); +``` + +> Notice: The `filePath` is the only required field, if it is empty, `.build` and `.toCommand` +> will revert. + +#### **`build(Fe self) → (bytes)`** + +Builds a binary file from a `.fe` file. + +#### **`toCommand(Fe self) → (Command)`** + +Converts the `Fe` struct into a `Command` struct. + +#### **`setCompilerPath(Fe self, string compilerPath) → (Fe)`** + +Overwrites the compiler path. + +#### **`setFilePath(Fe self, string filePath) → (Fe)`** + +Overwrites the file path. + +#### **`setOutputDir(Fe self, string outputDir) → (Fe)`** + +Overwrites the default artifacts directory. + +#### **`setOverwrite(Fe memory self, bool overwrite) → (Fe)`** + +Sets the build command overwrite flag. If `true` the contents of `outputDir` will be overwritten. + +#### **`getBytecode(Fe memory self, string contractName) → (bytes)`** + +Returns the bytecode from a compiled `Fe` contract. diff --git a/docs/src/reference/modules/invariants.md b/docs/src/reference/modules/invariants.md new file mode 100644 index 00000000..4d8dee7f --- /dev/null +++ b/docs/src/reference/modules/invariants.md @@ -0,0 +1,73 @@ +# Invariants + + ```solidity + struct FuzzSelector { + address addr; + bytes4[] selectors; +} +``` + +#### **`excludeContract(address newExcludedContract)`** + +Excludes a contract from the invariant runs. This means that no transactions will be sent to this contract. + +#### **`excludeContracts(address[] memory newExcludedContracts)`** + +Excludes multiple contracts from the invariant runs. This means that no transactions will be sent to these contracts. + +#### **`excludeSender(address newExcludedSender)`** + +Excludes a sender from the invariant runs. This means that the address will not be used as the sender of a transaction. + +#### **`excludeSenders(address[] memory newExcludedSenders)`** + +Excludes multiple senders from the invariant runs. This means that these addresses will not be used as the senders of transactions. + +#### **`excludeArtifact(string memory newExcludedArtifact)`** + +Excludes an artifact from the invariant runs. This means that contracts with this artifact will not be targeted. + +#### **`excludeArtifacts(string[] memory newExcludedArtifacts)`** + +Excludes multiple artifacts from the invariant runs. This means that contracts with these artifacts will not be targeted. + +#### **`targetArtifact(string memory newTargetedArtifact)`** + +Targets an artifact in the invariant runs. This means that contracts with this artifact will be specifically targeted. + +#### **`targetArtifacts(string[] memory newTargetedArtifacts)`** + +Targets multiple artifacts in the invariant runs. This means that contracts with these artifacts will be specifically targeted. + +#### **`targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector)`** + +Targets an artifact selector in the invariant runs. This means that the specific artifact selector will be targeted. + +#### **`targetArtifactSelectors(FuzzSelector[] memory newTargetedArtifactSelectors)`** + +Targets multiple artifact selectors in the invariant runs. This means that these specific artifact selectors will be targeted. + +#### **`targetContract(address newTargetedContract)`** + +Targets a contract in the invariant runs. This means that transactions will be specifically sent to this contract. + +#### **`targetContracts(address[] memory newTargetedContracts)`** + +Targets multiple contracts in the invariant runs. This means that transactions will be specifically sent to these contracts. + +#### **`targetSelector(FuzzSelector memory newTargetedSelector)`** + +Targets a selector in the invariant runs. This means that the specific selector will be targeted. + +#### **`targetSelectors(FuzzSelector[] memory newTargetedSelectors)`** + +Targets multiple selectors in the invariant runs. This means that these specific selectors will be targeted. + +#### **`targetSender(address newTargetedSender)`** + +Targets a sender in the invariant runs. This means that the address will be specifically used as the sender of a transaction. + +#### **`targetSenders(address[] memory newTargetedSenders)`** + +Targets multiple senders in the invariant runs. This means that these addresses will be specifically used as the senders of transactions. + diff --git a/docs/src/testing/README.md b/docs/src/testing/README.md index f34c9c2d..93bbaa75 100644 --- a/docs/src/testing/README.md +++ b/docs/src/testing/README.md @@ -6,7 +6,7 @@ Vulcan provides a simple testing framework through the base `Test` contract and import { Test, expect } from "vulcan/test.sol"; contract ExampleTest is Test { - function testSomething() external { + function test_something() external { uint256 value = 1; expect(value).toEqual(1); expect(value).not.toEqual(2); @@ -15,3 +15,24 @@ contract ExampleTest is Test { } } ``` + +In addition to the basic testing framework, Vulcan also provides utilities to facilitate the use of Foundry's invariant testing. These functions are provided through the `invariants` module. + +```solidity +import { Test, invariants, accounts } from "vulcan/test.sol"; + +contract ExampleTest is Test { + function setUp() external { + // { Bootstrap invariant testing scenario } + + invariants.excludeContract(myContract); + + // Use 10 different senders + invariants.targetSenders(accounts.createMany(10)); + } + + function invariant_checkSomething() external { + //... + } +} +``` diff --git a/foundry.toml b/foundry.toml index 7496fe20..6afc1c3a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,7 +6,8 @@ ffi = true fs_permissions = [ { access = "read", path = "./out"}, { access = "read", path = "./test/fixtures/fs/read" }, - { access = "read-write", path = "./test/fixtures/fs/write" } + { access = "read-write", path = "./test/fixtures/fs/write" }, + { access = "read-write", path = "./test/fixtures/fe/output" } ] [rpc_endpoints] diff --git a/lib/forge-std b/lib/forge-std index 74cfb77e..1d9650e9 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 74cfb77e308dd188d2f58864aaf44963ae6b88b1 +Subproject commit 1d9650e951204a0ddce9ff89c32f1997984cef4d diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..54bdd58b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2253 @@ +{ + "name": "vulcan", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vulcan", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@commitlint/cli": "^17.7.1", + "@commitlint/config-conventional": "^17.7.0", + "husky": "^8.0.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", + "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@commitlint/cli": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.7.1.tgz", + "integrity": "sha512-BCm/AT06SNCQtvFv921iNhudOHuY16LswT0R3OeolVGLk8oP+Rk9TfQfgjH7QPMjhvp76bNqGFEcpKojxUNW1g==", + "dev": true, + "dependencies": { + "@commitlint/format": "^17.4.4", + "@commitlint/lint": "^17.7.0", + "@commitlint/load": "^17.7.1", + "@commitlint/read": "^17.5.1", + "@commitlint/types": "^17.4.4", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.7.0.tgz", + "integrity": "sha512-iicqh2o6et+9kWaqsQiEYZzfLbtoWv9uZl8kbI8EGfnc0HeGafQBF7AJ0ylN9D/2kj6txltsdyQs8+2fTMwWEw==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^6.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", + "integrity": "sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.4.4", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/ensure": { + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.6.7.tgz", + "integrity": "sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.4.4", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", + "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/format": { + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", + "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.4.4", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz", + "integrity": "sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.4.4", + "semver": "7.5.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/lint": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.7.0.tgz", + "integrity": "sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^17.7.0", + "@commitlint/parse": "^17.7.0", + "@commitlint/rules": "^17.7.0", + "@commitlint/types": "^17.4.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.7.1.tgz", + "integrity": "sha512-S/QSOjE1ztdogYj61p6n3UbkUvweR17FQ0zDbNtoTLc+Hz7vvfS7ehoTMQ27hPSjVBpp7SzEcOQu081RLjKHJQ==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^17.6.7", + "@commitlint/execute-rule": "^17.4.0", + "@commitlint/resolve-extends": "^17.6.7", + "@commitlint/types": "^17.4.4", + "@types/node": "20.4.7", + "chalk": "^4.1.0", + "cosmiconfig": "^8.0.0", + "cosmiconfig-typescript-loader": "^4.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0", + "resolve-from": "^5.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.6.4 || ^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/message": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", + "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/parse": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.7.0.tgz", + "integrity": "sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag==", + "dev": true, + "dependencies": { + "@commitlint/types": "^17.4.4", + "conventional-changelog-angular": "^6.0.0", + "conventional-commits-parser": "^4.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/read": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.5.1.tgz", + "integrity": "sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^17.4.0", + "@commitlint/types": "^17.4.4", + "fs-extra": "^11.0.0", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz", + "integrity": "sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^17.6.7", + "@commitlint/types": "^17.4.4", + "import-fresh": "^3.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/rules": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.7.0.tgz", + "integrity": "sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^17.6.7", + "@commitlint/message": "^17.4.2", + "@commitlint/to-lines": "^17.4.0", + "@commitlint/types": "^17.4.4", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", + "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", + "dev": true, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", + "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/types": { + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", + "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.4.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.7.tgz", + "integrity": "sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", + "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "dev": true, + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", + "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "dev": true, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "ts-node": ">=10", + "typescript": ">=4" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..2a9cbda5 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "vulcan", + "version": "1.0.0", + "description": "

Vulcan

", + "main": "index.js", + "keywords": [], + "author": "Nomoi", + "license": "MIT", + "devDependencies": { + "@commitlint/cli": "^17.7.1", + "@commitlint/config-conventional": "^17.7.0", + "husky": "^8.0.3" + }, + "scripts": { + "prepare": "husky install" + } +} diff --git a/src/_modules/Accounts.sol b/src/_modules/Accounts.sol index bece367a..6a38154f 100644 --- a/src/_modules/Accounts.sol +++ b/src/_modules/Accounts.sol @@ -3,7 +3,9 @@ pragma solidity >=0.8.13 <0.9.0; import {stdStorage, StdStorage} from "forge-std/StdStorage.sol"; +import {strings} from "./Strings.sol"; import "./Vulcan.sol"; +import {formatError} from "../_utils/formatError.sol"; library accountsSafe { /// @dev Reads the storage at the specified `slot` for the given `who` address and returns the content. @@ -86,6 +88,12 @@ library accountsSafe { return who; } + /// @dev Creates an address without label. + function create() internal returns (address) { + uint256 id = _incrementId(); + return derive(uint256(keccak256(abi.encode(id)))); + } + /// @dev Creates an address using the hash of the specified `name` as the private key and adds a label to the address. /// @param name The name to use as the basis for the address. /// @return The newly created address. @@ -139,6 +147,49 @@ library accountsSafe { function getDeploymentAddress(address who) internal view returns (address) { return getDeploymentAddress(who, getNonce(who)); } + + /// @dev Generates an array of addresses with a specific length. + /// @param length The amount of addresses to generate. + function createMany(uint256 length) internal returns (address[] memory) { + require(length > 0, _formatError("createMany(uint256)", "Invalid length for addresses array")); + + address[] memory addresses = new address[](length); + + for (uint256 i; i < length; i++) { + addresses[i] = create(); + } + + return addresses; + } + + /// @dev Generates an array of addresses with a specific length and a prefix as label. + /// The label for each address will be `{prefix}_{i}`. + /// @param length The amount of addresses to generate. + /// @param prefix The prefix of the label for each address. + function createMany(uint256 length, string memory prefix) internal returns (address[] memory) { + require(length > 0, "accounts: invalid length for addresses array"); + + address[] memory addresses = new address[](length); + + for (uint256 i; i < length; i++) { + addresses[i] = create(string.concat(prefix, "_", strings.toString(i))); + } + + return addresses; + } + + function _incrementId() private returns (uint256 count) { + bytes32 slot = keccak256("vulcan.accounts.id.counter"); + + assembly { + count := sload(slot) + sstore(slot, add(count, 1)) + } + } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("accounts", func, message); + } } library accounts { @@ -196,6 +247,10 @@ library accounts { return accountsSafe.label(who, lbl); } + function create() internal returns (address) { + return accountsSafe.create(); + } + function create(string memory name) internal returns (address) { return accountsSafe.create(name); } @@ -369,4 +424,10 @@ library accounts { vulcan.hevm.etch(self, code); return self; } + + /// @dev Generates an array of addresses with a specific length. + /// @param length The amount of addresses to generate. + function createMany(uint256 length) internal returns (address[] memory) { + return accountsSafe.createMany(length); + } } diff --git a/src/_modules/Commands.sol b/src/_modules/Commands.sol index 6a5d225a..59c4cf55 100644 --- a/src/_modules/Commands.sol +++ b/src/_modules/Commands.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; +import {VmSafe} from "forge-std/Vm.sol"; import {vulcan} from "./Vulcan.sol"; /// @dev Struct used to hold command parameters. Useful for creating commands that can be run @@ -9,6 +10,13 @@ struct Command { string[] inputs; } +struct CommandResult { + int32 exitCode; + bytes stdout; + bytes stderr; + Command command; +} + library commands { using commands for *; @@ -147,97 +155,137 @@ library commands { /// @dev Runs a command using the specified `Command` struct as parameters and returns the result. /// @param self The `Command` struct that holds the parameters of the command. /// @return The result of the command as a bytes array. - function run(Command memory self) internal returns (bytes memory) { + function run(Command memory self) internal returns (CommandResult memory) { return self.inputs.run(); } /// @dev Runs a command with the specified `inputs` as parameters and returns the result. /// @param inputs An array of strings representing the parameters of the command. - /// @return The result of the command as a bytes array. - function run(string[] memory inputs) internal returns (bytes memory) { - return vulcan.hevm.ffi(inputs); + /// @return result The result of the command as a bytes array. + function run(string[] memory inputs) internal returns (CommandResult memory result) { + VmSafe.FfiResult memory ffiResult = vulcan.hevm.tryFfi(inputs); + + result.exitCode = ffiResult.exit_code; + result.stdout = ffiResult.stdout; + result.stderr = ffiResult.stderr; + result.command = Command(inputs); } - function run(string[1] memory inputs) internal returns (bytes memory) { + function run(string[1] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[2] memory inputs) internal returns (bytes memory) { + function run(string[2] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[3] memory inputs) internal returns (bytes memory) { + function run(string[3] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[4] memory inputs) internal returns (bytes memory) { + function run(string[4] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[5] memory inputs) internal returns (bytes memory) { + function run(string[5] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[6] memory inputs) internal returns (bytes memory) { + function run(string[6] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[7] memory inputs) internal returns (bytes memory) { + function run(string[7] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[8] memory inputs) internal returns (bytes memory) { + function run(string[8] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[9] memory inputs) internal returns (bytes memory) { + function run(string[9] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[10] memory inputs) internal returns (bytes memory) { + function run(string[10] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[11] memory inputs) internal returns (bytes memory) { + function run(string[11] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[12] memory inputs) internal returns (bytes memory) { + function run(string[12] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[13] memory inputs) internal returns (bytes memory) { + function run(string[13] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[14] memory inputs) internal returns (bytes memory) { + function run(string[14] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[15] memory inputs) internal returns (bytes memory) { + function run(string[15] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[16] memory inputs) internal returns (bytes memory) { + function run(string[16] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[17] memory inputs) internal returns (bytes memory) { + function run(string[17] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[18] memory inputs) internal returns (bytes memory) { + function run(string[18] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[19] memory inputs) internal returns (bytes memory) { + function run(string[19] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } - function run(string[20] memory inputs) internal returns (bytes memory) { + function run(string[20] memory inputs) internal returns (CommandResult memory) { return _toDynamic(inputs).run(); } + /// @dev Checks if a `CommandResult` returned an `ok` exit code. + function isOk(CommandResult memory self) internal pure returns (bool) { + return self.exitCode == 0; + } + + /// @dev Checks if a `CommandResult` struct is an error. + function isError(CommandResult memory self) internal pure returns (bool) { + return !self.isOk(); + } + + /// @dev Returns the output of a `CommandResult` or reverts if the result was an error. + function unwrap(CommandResult memory self) internal pure returns (bytes memory) { + string memory error; + + if (self.isError()) { + error = string.concat("Failed to run command ", self.command.toString()); + + if (self.stderr.length > 0) { + error = string.concat(error, ":\n\n", string(self.stderr)); + } + } + + return expect(self, error); + } + + /// @dev Returns the output of a `CommandResult` or reverts if the result was an error. + /// @param customError The error message that will be used when reverting. + function expect(CommandResult memory self, string memory customError) internal pure returns (bytes memory) { + if (self.isError()) { + revert(customError); + } + + return self.stdout; + } + function _toDynamic(string[1] memory inputs) private pure returns (string[] memory _inputs) { _inputs = new string[](1); _inputs[0] = inputs[0]; @@ -378,3 +426,4 @@ library commands { } using commands for Command global; +using commands for CommandResult global; diff --git a/src/_modules/Config.sol b/src/_modules/Config.sol index d64d485d..049cd6cc 100644 --- a/src/_modules/Config.sol +++ b/src/_modules/Config.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import {Vm as Hevm} from "forge-std/Vm.sol"; -import {vulcan} from "./Vulcan.sol"; +import {vulcan, Hevm} from "./Vulcan.sol"; /// @dev Struct that represents an RPC endpoint struct Rpc { diff --git a/src/_modules/Context.sol b/src/_modules/Context.sol index d7f2fde8..84ea7623 100644 --- a/src/_modules/Context.sol +++ b/src/_modules/Context.sol @@ -5,6 +5,7 @@ import "./Vulcan.sol"; import "./Accounts.sol"; import "./Strings.sol"; import "../_utils/println.sol"; +import {formatError} from "../_utils/formatError.sol"; type Context is bytes32; @@ -74,7 +75,7 @@ library ctxSafe { function startGasReport(string memory name) internal { if (bytes(name).length > 32) { - revert("ctx.startGasReport: Gas report name can't have more than 32 characters"); + revert(_formatError("startGasReport", "Gas report name can't have more than 32 characters")); } bytes32 b32Name = bytes32(bytes(name)); @@ -91,10 +92,14 @@ library ctxSafe { bytes32 valueSlot = keccak256(abi.encodePacked("vulcan.ctx.gasReport", b32Name)); uint256 prevGas = uint256(accounts.readStorage(address(vulcan.hevm), valueSlot)); if (gas > prevGas) { - revert("ctx.endGasReport: Gas used can't have a negative value"); + revert(_formatError("endGasReport", "Gas used can't have a negative value")); } println(string.concat("gas(", string(abi.encodePacked(b32Name)), "):", strings.toString(prevGas - gas))); } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("ctx", func, message); + } } library ctx { diff --git a/src/_modules/Fe.sol b/src/_modules/Fe.sol new file mode 100644 index 00000000..6c22ac9e --- /dev/null +++ b/src/_modules/Fe.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import "./Commands.sol"; +import "./Strings.sol"; +import "./Fs.sol"; +import {formatError} from "../_utils/formatError.sol"; + +struct Fe { + string compilerPath; + string filePath; + string outputDir; + bool overwrite; +} + +library fe { + using strings for bytes32; + + /// @dev Creates a new `Fe` struct with default values. + function create() internal pure returns (Fe memory) { + return Fe({compilerPath: "fe", filePath: "", outputDir: "", overwrite: false}); + } + + /// @dev Builds a binary file from a `.fe` file. + /// @param self The `Fe` struct to build. + function build(Fe memory self) internal returns (CommandResult memory) { + return self.toCommand().run(); + } + + /// @dev Transforms a `Fe` struct to a `Command` struct. + /// @param self The `Fe` struct to transform. + function toCommand(Fe memory self) internal pure returns (Command memory) { + Command memory command = commands.create(self.compilerPath); + + command = command.arg("build").args(["-e", "bytecode"]); + + if (bytes(self.outputDir).length == 0) { + self.outputDir = "./out/__TMP/fe_builds"; + } + + command = command.args(["-o", self.outputDir]); + if (self.overwrite) command = command.arg("--overwrite"); + + command = command.arg(self.filePath); + + return command; + } + + /// @dev Sets the `fe` compiler path. + /// @param self The `Fe` struct to modify. + /// @param compilerPath The new compiler path. + function setCompilerPath(Fe memory self, string memory compilerPath) internal pure returns (Fe memory) { + self.compilerPath = compilerPath; + return self; + } + + /// @dev Sets the `fe` file path to build. + /// @param self The `Fe` struct to modify. + /// @param filePath The path to the `.fe` file to build. + function setFilePath(Fe memory self, string memory filePath) internal pure returns (Fe memory) { + self.filePath = filePath; + return self; + } + + /// @dev Sets the `fe` build command output directory. + /// @param self The `Fe` struct to modify. + /// @param outputDir The directory where the binary file will be saved. + function setOutputDir(Fe memory self, string memory outputDir) internal pure returns (Fe memory) { + self.outputDir = outputDir; + return self; + } + + /// @dev Sets the `fe` build command overwrite flag. + /// @param self The `Fe` struct to modify. + /// @param overwrite If true it will overwrite the `outputDir with the new build binaries. + function setOverwrite(Fe memory self, bool overwrite) internal pure returns (Fe memory) { + self.overwrite = overwrite; + return self; + } + + /// @dev Obtains the bytecode of a compiled contract with `contractName`. + /// @param contractName The name of the contract from which to retrive the bytecode. + function getBytecode(Fe memory self, string memory contractName) internal view returns (bytes memory) { + string memory path = string.concat(self.outputDir, "/", contractName, "/", contractName, ".bin"); + + if (!fs.fileExists(path)) { + revert(_formatError("getBytecode(Fe,string))", "Contract not found")); + } + + return fs.readFileBinary(path); + } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("fe", func, message); + } +} + +using fe for Fe global; diff --git a/src/_modules/Fmt.sol b/src/_modules/Fmt.sol index 4606b8a5..c0a1a91e 100644 --- a/src/_modules/Fmt.sol +++ b/src/_modules/Fmt.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import "./Console.sol"; import "./Strings.sol"; +import {formatError} from "../_utils/formatError.sol"; enum Type { Bool, @@ -128,7 +128,7 @@ library fmt { } else if (typeHash == BYTES32_HASH || typeHash == ABBREVIATED_BYTES32_HASH) { t = Type.Bytes32; } else { - revert("Unsupported placeholder type"); + revert(_formatError("_findPlaceholder(bytes,uint256)", "Unsupported placeholder type")); } bytes memory mod = modifierStart == placeholderEnd @@ -152,7 +152,7 @@ library fmt { return new bytes(0); } - require(start + len <= data.length, "Slice out of bounds"); + require(start + len <= data.length, _formatError("_readSlice(bytes,uint256,uint256)", "Slice out of bounds")); bytes memory result = new bytes(len); @@ -189,7 +189,7 @@ library fmt { uint256 len = uint256(_readWord(data, offset)); value = string(_readSlice(data, offset + 32, len)); } else { - revert("Unsupported type"); + revert(_formatError("_decodeArgs(Placeholder[],bytes)", "Unsupported type")); } result[i] = value; } @@ -226,7 +226,7 @@ library fmt { return string.concat(integer, ".", remainder); } else { - revert("Unsupported modifier"); + revert(_formatError("_display(uint256,bytes)", "Unsupported modifier")); } } @@ -267,4 +267,8 @@ library fmt { return string(result); } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("fmt", func, message); + } } diff --git a/src/_modules/Fs.sol b/src/_modules/Fs.sol index 88486b53..64a81587 100644 --- a/src/_modules/Fs.sol +++ b/src/_modules/Fs.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import {Vm as Hevm} from "forge-std/Vm.sol"; import "./Vulcan.sol"; struct FsMetadata { diff --git a/src/_modules/Gas.sol b/src/_modules/Gas.sol index 23abfd62..c9121169 100644 --- a/src/_modules/Gas.sol +++ b/src/_modules/Gas.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.17; import "./Vulcan.sol"; import "./Accounts.sol"; +import {formatError} from "../_utils/formatError.sol"; library gas { bytes32 constant GAS_MEASUREMENTS_MAGIC = keccak256("vulcan.gas.measurements.magic"); @@ -19,7 +20,7 @@ library gas { uint256 startGas = uint256(accounts.readStorage(address(vulcan.hevm), startSlot)); if (endGas > startGas) { - revert("gas.stopRecord: Gas used can't have a negative value"); + revert(_formatError("stopRecord", "Gas used can't have a negative value")); } bytes32 endSlot = keccak256(abi.encode(GAS_MEASUREMENTS_MAGIC, name, "end")); @@ -43,4 +44,8 @@ library gas { return startGas - endGas; } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("gas", func, message); + } } diff --git a/src/_modules/Huff.sol b/src/_modules/Huff.sol index 4b793dd0..6385eb26 100644 --- a/src/_modules/Huff.sol +++ b/src/_modules/Huff.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.13 <0.9.0; import "./Commands.sol"; import "./Strings.sol"; +import {formatError} from "../_utils/formatError.sol"; struct Huffc { string compilerPath; @@ -31,15 +32,13 @@ library huff { }); } - function compile(Huffc memory self) internal returns (bytes memory) { - bytes memory output = self.toCommand().run(); - // TODO: add error handling - return output; + function compile(Huffc memory self) internal returns (CommandResult memory) { + return self.toCommand().run(); } function toCommand(Huffc memory self) internal pure returns (Command memory) { Command memory command = commands.create(self.compilerPath); - require(bytes(self.filePath).length > 0, "self.filePath not set"); + require(bytes(self.filePath).length > 0, _formatError("toCommand(Huffc)", "self.filePath not set")); if (bytes(self.outputPath).length > 0) command = command.args(["-ao", self.outputPath]); if (bytes(self.mainName).length > 0) command = command.args(["-m", self.mainName]); @@ -105,4 +104,8 @@ library huff { self.constantOverrides = overrides; return self; } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("huff", func, message); + } } diff --git a/src/_modules/Invariants.sol b/src/_modules/Invariants.sol new file mode 100644 index 00000000..a463a54a --- /dev/null +++ b/src/_modules/Invariants.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +/// @title FuzzSelector +/// @dev A struct that represents a Fuzz Selector +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +/// @title InvariantsBase +/// @dev An abstract contract that defines the base for Invariants +abstract contract InvariantsBase { + /// @dev Returns the excluded artifacts + /// @return The array of excluded artifacts + function excludeArtifacts() public view returns (string[] memory) { + return invariants.getState().excludedArtifacts; + } + + /// @dev Returns the excluded contracts + /// @return The array of excluded contracts + function excludeContracts() public view returns (address[] memory) { + return invariants.getState().excludedContracts; + } + + /// @dev Returns the excluded senders + /// @return The array of excluded senders + function excludeSenders() public view returns (address[] memory) { + return invariants.getState().excludedSenders; + } + + /// @dev Returns the targeted artifacts + /// @return The array of targeted artifacts + function targetArtifacts() public view returns (string[] memory) { + return invariants.getState().targetedArtifacts; + } + + /// @dev Returns the targeted artifact selectors + /// @return The array of targeted artifact selectors + function targetArtifactSelectors() public view returns (FuzzSelector[] memory) { + return invariants.getState().targetedArtifactSelectors; + } + + /// @dev Returns the targeted contracts + /// @return The array of targeted contracts + function targetContracts() public view returns (address[] memory) { + return invariants.getState().targetedContracts; + } + + /// @dev Returns the targeted selectors + /// @return The array of targeted selectors + function targetSelectors() public view returns (FuzzSelector[] memory) { + return invariants.getState().targetedSelectors; + } + + /// @dev Returns the targeted senders + /// @return The array of targeted senders + function targetSenders() public view returns (address[] memory) { + return invariants.getState().targetedSenders; + } +} + +library invariants { + struct State { + address[] excludedContracts; + address[] excludedSenders; + address[] targetedContracts; + address[] targetedSenders; + string[] excludedArtifacts; + string[] targetedArtifacts; + FuzzSelector[] targetedArtifactSelectors; + FuzzSelector[] targetedSelectors; + } + + /// @dev Returns the state struct that contains the invariants related data + /// @return state The invariants state struct + function getState() internal pure returns (State storage state) { + bytes32 slot = keccak256("vulcan.invariants.state"); + assembly { + state.slot := slot + } + } + + /// @dev Excludes a contract + /// @param newExcludedContract The contract to be excluded + function excludeContract(address newExcludedContract) internal { + getState().excludedContracts.push(newExcludedContract); + } + + /// @dev Excludes multiple contracts + /// @param newExcludedContracts The contracts to be excluded + function excludeContracts(address[] memory newExcludedContracts) internal { + for (uint256 i = 0; i < newExcludedContracts.length; i++) { + excludeContract(newExcludedContracts[i]); + } + } + + /// @dev Excludes a sender + /// @param newExcludedSender The sender to be excluded + function excludeSender(address newExcludedSender) internal { + getState().excludedSenders.push(newExcludedSender); + } + + /// @dev Excludes multiple senders + /// @param newExcludedSenders The senders to be excluded + function excludeSenders(address[] memory newExcludedSenders) internal { + for (uint256 i = 0; i < newExcludedSenders.length; i++) { + excludeSender(newExcludedSenders[i]); + } + } + + /// @dev Excludes an artifact + /// @param newExcludedArtifact The artifact to be excluded + function excludeArtifact(string memory newExcludedArtifact) internal { + getState().excludedArtifacts.push(newExcludedArtifact); + } + + /// @dev Excludes multiple artifacts + /// @param newExcludedArtifacts The artifacts to be excluded + function excludeArtifacts(string[] memory newExcludedArtifacts) internal { + for (uint256 i = 0; i < newExcludedArtifacts.length; i++) { + excludeArtifact(newExcludedArtifacts[i]); + } + } + + /// @dev Targets an artifact + /// @param newTargetedArtifact The artifact to be targeted + function targetArtifact(string memory newTargetedArtifact) internal { + getState().targetedArtifacts.push(newTargetedArtifact); + } + + /// @dev Targets multiple artifacts + /// @param newTargetedArtifacts The artifacts to be targeted + function targetArtifacts(string[] memory newTargetedArtifacts) internal { + for (uint256 i = 0; i < newTargetedArtifacts.length; i++) { + targetArtifact(newTargetedArtifacts[i]); + } + } + + /// @dev Targets an artifact selector + /// @param newTargetedArtifactSelector The artifact selector to be targeted + function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector) internal { + getState().targetedArtifactSelectors.push(newTargetedArtifactSelector); + } + + /// @dev Targets multiple artifact selectors + /// @param newTargetedArtifactSelectors The artifact selectors to be targeted + function targetArtifactSelectors(FuzzSelector[] memory newTargetedArtifactSelectors) internal { + for (uint256 i = 0; i < newTargetedArtifactSelectors.length; i++) { + targetArtifactSelector(newTargetedArtifactSelectors[i]); + } + } + + /// @dev Targets a contract + /// @param newTargetedContract The contract to be targeted + function targetContract(address newTargetedContract) internal { + getState().targetedContracts.push(newTargetedContract); + } + + /// @dev Targets multiple contracts + /// @param newTargetedContracts The contracts to be targeted + function targetContracts(address[] memory newTargetedContracts) internal { + for (uint256 i = 0; i < newTargetedContracts.length; i++) { + targetContract(newTargetedContracts[i]); + } + } + + /// @dev Targets a selector + /// @param newTargetedSelector The selector to be targeted + function targetSelector(FuzzSelector memory newTargetedSelector) internal { + getState().targetedSelectors.push(newTargetedSelector); + } + + /// @dev Targets multiple selectors + /// @param newTargetedSelectors The selectors to be targeted + function targetSelectors(FuzzSelector[] memory newTargetedSelectors) internal { + for (uint256 i = 0; i < newTargetedSelectors.length; i++) { + targetSelector(newTargetedSelectors[i]); + } + } + + /// @dev Targets a sender + /// @param newTargetedSender The sender to be targeted + function targetSender(address newTargetedSender) internal { + getState().targetedSenders.push(newTargetedSender); + } + + /// @dev Targets multiple senders + /// @param newTargetedSenders The senders to be targeted + function targetSenders(address[] memory newTargetedSenders) internal { + for (uint256 i = 0; i < newTargetedSenders.length; i++) { + targetSender(newTargetedSenders[i]); + } + } +} diff --git a/src/_modules/Json.sol b/src/_modules/Json.sol index e5a41aa2..dd5cf658 100644 --- a/src/_modules/Json.sol +++ b/src/_modules/Json.sol @@ -159,12 +159,7 @@ library json { /// @dev Creates a new JsonObject struct. /// @return The JsonObject struct. function create() internal returns (JsonObject memory) { - bytes32 slot = keccak256("vulcan.json.id.counter"); - uint256 next = uint256(accounts.readStorage(address(this), slot)) + 1; - accounts.setStorage(address(this), slot, bytes32(next)); - - string memory id = string(abi.encodePacked(address(this), next)); - + string memory id = string(abi.encodePacked(address(this), _incrementId())); return JsonObject({id: id, serialized: ""}); } @@ -353,6 +348,15 @@ library json { function write(JsonObject memory obj, string memory path, string memory key) internal { vulcan.hevm.writeJson(obj.serialized, path, key); } + + function _incrementId() private returns (uint256 count) { + bytes32 slot = keccak256("vulcan.json.id.counter"); + + assembly { + count := sload(slot) + sstore(slot, add(count, 1)) + } + } } using json for JsonObject global; diff --git a/src/_modules/Watchers.sol b/src/_modules/Watchers.sol index a1f59eb4..f2acc45f 100644 --- a/src/_modules/Watchers.sol +++ b/src/_modules/Watchers.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import "./Console.sol"; import "./Vulcan.sol"; import "./Events.sol"; import "./Accounts.sol"; import "./Context.sol"; +import {formatError} from "../_utils/formatError.sol"; struct Call { bytes callData; @@ -39,7 +39,7 @@ library watchers { /// @return The Watcher implementation. function watcher(address target) internal view returns (Watcher) { address _watcher = watcherAddress(target); - require(_watcher.code.length != 0, "Address doesn't have a watcher"); + require(_watcher.code.length != 0, _formatError("watcher(address)", "Address doesn't have a watcher")); return Watcher(_watcher); } @@ -49,7 +49,7 @@ library watchers { /// @return The Watcher implementation. function watch(address target) internal returns (Watcher) { address _watcher = watcherAddress(target); - require(_watcher.code.length == 0, "Address already has a watcher"); + require(_watcher.code.length == 0, _formatError("watch(address)", "Address already has a watcher")); accounts.setCode(_watcher, type(Watcher).runtimeCode); @@ -126,6 +126,10 @@ library watchers { _watcher.disableCaptureReverts(); return _watcher; } + + function _formatError(string memory func, string memory message) private pure returns (string memory) { + return formatError("watchers", func, message); + } } contract Watcher { diff --git a/src/_utils/bound.sol b/src/_utils/bound.sol new file mode 100644 index 00000000..ecc78d60 --- /dev/null +++ b/src/_utils/bound.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import {formatError} from "./formatError.sol"; + +// Extracted from forge-std stdUtils: https://github.com/foundry-rs/forge-std/blob/7b4876e8de2a232a54159035f173e35421000c19/src/StdUtils.sol +// The main difference is that we use file-level functions instead of an abstract contract. + +uint256 constant UINT256_MAX = type(uint256).max; +uint256 constant INT256_MIN_ABS = uint256(type(int256).max) + 1; + +function bound(uint256 x, uint256 min, uint256 max) pure returns (uint256 result) { + require(min <= max, formatError("_utils", "bound(uint256,uint256,uint256)", "Max is less than min.")); + // If x is between min and max, return x directly. This is to ensure that dictionary values + // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 + if (x >= min && x <= max) return x; + + uint256 size = max - min + 1; + + // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. + // This helps ensure coverage of the min/max values. + if (x <= 3 && size > x) return min + x; + if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); + + // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. + if (x > max) { + uint256 diff = x - max; + uint256 rem = diff % size; + if (rem == 0) return max; + result = min + rem - 1; + } else if (x < min) { + uint256 diff = min - x; + uint256 rem = diff % size; + if (rem == 0) return min; + result = max - rem + 1; + } +} + +function bound(int256 x, int256 min, int256 max) pure returns (int256 result) { + require(min <= max, formatError("_utils", "bound(int256,int256,int256)", "Max is less than min.")); + + // Shifting all int256 values to uint256 to use _bound function. The range of two types are: + // int256 : -(2**255) ~ (2**255 - 1) + // uint256: 0 ~ (2**256 - 1) + // So, add 2**255, INT256_MIN_ABS to the integer values. + // + // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. + // So, use `~uint256(x) + 1` instead. + uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); + uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); + uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); + + uint256 y = bound(_x, _min, _max); + + // To move it back to int256 value, subtract INT256_MIN_ABS at here. + result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); +} diff --git a/src/_utils/formatError.sol b/src/_utils/formatError.sol new file mode 100644 index 00000000..495b16d6 --- /dev/null +++ b/src/_utils/formatError.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +function formatError(string memory module, string memory func, string memory message) pure returns (string memory) { + return string.concat("vulcan.", module, ".", func, ": ", message); +} diff --git a/src/_utils/println.sol b/src/_utils/println.sol index 5ee09668..067391ae 100644 --- a/src/_utils/println.sol +++ b/src/_utils/println.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import {console} from "../_modules/Console.sol"; import {fmt} from "../_modules/Fmt.sol"; +import {rawConsoleLog} from "./rawConsole.sol"; -function println(string memory template, bytes memory args) pure { - console.log(fmt.format(template, args)); +function println(string memory template, bytes memory args) view { + rawConsoleLog(fmt.format(template, args)); } -function println(string memory arg) pure { - console.log(arg); +function println(string memory arg) view { + rawConsoleLog(arg); } diff --git a/src/_utils/rawConsole.sol b/src/_utils/rawConsole.sol new file mode 100644 index 00000000..057455b9 --- /dev/null +++ b/src/_utils/rawConsole.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +function rawConsoleLog(string memory arg) view { + address console2Addr = 0x000000000000000000636F6e736F6c652e6c6f67; + (bool status,) = console2Addr.staticcall(abi.encodeWithSignature("log(string)", arg)); + status; +} diff --git a/src/script.sol b/src/script.sol index 4b3bfa33..aadc87c1 100644 --- a/src/script.sol +++ b/src/script.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.13 <0.9.0; import {console} from "./_modules/Console.sol"; import {vulcan} from "./_modules/Vulcan.sol"; import {accountsSafe as accounts, accounts as accountsUnsafe} from "./_modules/Accounts.sol"; -import {commands, Command} from "./_modules/Commands.sol"; +import {commands, Command, CommandResult} from "./_modules/Commands.sol"; import {ctxSafe as ctx, ctx as ctxUnsafe} from "./_modules/Context.sol"; import {env} from "./_modules/Env.sol"; import {events} from "./_modules/Events.sol"; @@ -15,8 +15,11 @@ import {strings} from "./_modules/Strings.sol"; import {watchers as watchersUnsafe} from "./_modules/Watchers.sol"; import {config, Rpc} from "./_modules/Config.sol"; import {fmt} from "./_modules/Fmt.sol"; +import {bound} from "./_utils/bound.sol"; import {format} from "./_utils/format.sol"; import {println} from "./_utils/println.sol"; +import {huff, Huffc} from "./_modules/Huff.sol"; +import {fe, Fe} from "./_modules/Fe.sol"; contract Script { bool public IS_SCRIPT = true; diff --git a/src/test.sol b/src/test.sol index 2ba35e69..a50f1abc 100644 --- a/src/test.sol +++ b/src/test.sol @@ -5,7 +5,7 @@ import {console} from "./_modules/Console.sol"; import {vulcan, Log} from "./_modules/Vulcan.sol"; import {any} from "./_modules/Any.sol"; import {accounts} from "./_modules/Accounts.sol"; -import {commands, Command} from "./_modules/Commands.sol"; +import {commands, Command, CommandResult} from "./_modules/Commands.sol"; import {ctx} from "./_modules/Context.sol"; import {env} from "./_modules/Env.sol"; import {events} from "./_modules/Events.sol"; @@ -14,16 +14,20 @@ import {forks, Fork} from "./_modules/Forks.sol"; import {fs, FsMetadata} from "./_modules/Fs.sol"; import {gas} from "./_modules/Gas.sol"; import {huff, Huffc} from "./_modules/Huff.sol"; +import {InvariantsBase, invariants} from "./_modules/Invariants.sol"; import {json, JsonObject} from "./_modules/Json.sol"; import {strings} from "./_modules/Strings.sol"; import {watchers, Watcher} from "./_modules/Watchers.sol"; import {config, Rpc} from "./_modules/Config.sol"; import {fmt} from "./_modules/Fmt.sol"; +import {fe, Fe} from "./_modules/Fe.sol"; import {format} from "./_utils/format.sol"; import {println} from "./_utils/println.sol"; +import {bound} from "./_utils/bound.sol"; +import {formatError} from "./_utils/formatError.sol"; // @dev Main entry point to Vulcan tests -contract Test { +contract Test is InvariantsBase { bool public IS_TEST = true; constructor() { @@ -44,7 +48,7 @@ contract Test { } if (!post) { - revert("Didn't fail"); + revert(formatError("test", "shouldFail()", "Test expected to fail")); } vulcan.clearFailure(); diff --git a/test/ExampleTest.sol b/test/ExampleTest.sol index 6ade669a..50998bf0 100644 --- a/test/ExampleTest.sol +++ b/test/ExampleTest.sol @@ -1,6 +1,6 @@ pragma solidity >=0.8.13 <0.9.0; -import {Test, expect, accounts, ctx, console, vulcan, accounts} from "../src/test.sol"; +import {Test, expect, accounts, ctx, vulcan, accounts, println} from "../src/test.sol"; import {Sender} from "./mocks/Sender.sol"; contract ExampleTest is Test { @@ -21,8 +21,8 @@ contract ExampleTest is Test { expect(false).toEqual(false); } - function testConsoleLog() external pure { - console.log("hello world"); + function testConsoleLog() external view { + println("hello world"); } function testGetNonce() external { diff --git a/test/_modules/Accounts.t.sol b/test/_modules/Accounts.t.sol index 90eaa4d3..307cc776 100644 --- a/test/_modules/Accounts.t.sol +++ b/test/_modules/Accounts.t.sol @@ -228,6 +228,25 @@ contract AccountsTest is Test { expect(deployedAddress).toEqual(deploymentAddress); } + + function testCreateAddresWithoutName() external { + address first = accounts.create(); + address second = accounts.create(); + + expect(first).not.toEqual(second); + } + + function testCreateAddressesArray() external { + uint256 length = 20; + + address[] memory addresses = accounts.createMany(length); + + expect(addresses.length).toEqual(length); + + for (uint256 i; i < length; i++) { + expect(addresses[i]).toEqual(accounts.derive(uint256(keccak256(abi.encode(i))))); + } + } } contract TestToken { diff --git a/test/_modules/Commands.t.sol b/test/_modules/Commands.t.sol index 7f419bbb..a54cfd31 100644 --- a/test/_modules/Commands.t.sol +++ b/test/_modules/Commands.t.sol @@ -1,6 +1,6 @@ pragma solidity >=0.8.13 <0.9.0; -import {Test, expect, commands, Command} from "../../src/test.sol"; +import {Test, expect, commands, Command, CommandResult, ctx} from "../../src/test.sol"; contract CommandsTest is Test { using commands for *; @@ -15,14 +15,14 @@ contract CommandsTest is Test { string[2] memory inputs = ["echo", "'Hello, World!'"]; Command memory cmd = commands.create(inputs[0]).arg(inputs[1]); - expect(string(cmd.run())).toEqual(inputs[1]); + expect(string(cmd.run().stdout)).toEqual(inputs[1]); } function testItCanRunCommandsDirectly() external { string[2] memory inputs = ["echo", "'Hello, World!'"]; - bytes memory output = commands.run(inputs); + CommandResult memory result = commands.run(inputs); - expect(string(output)).toEqual(inputs[1]); + expect(string(result.stdout)).toEqual(inputs[1]); } function testCommandToString() external { @@ -30,4 +30,52 @@ contract CommandsTest is Test { expect(ping.toString()).toEqual("ping -c 1 nomoi.xyz"); } + + function testIsOk() external { + CommandResult memory result = commands.run(["echo", "'Hello World'"]); + + expect(result.isOk()).toBeTrue(); + } + + function testIsNotOk() external { + CommandResult memory result = commands.run(["forge", "--hlkfshjfhjas"]); + + expect(result.isOk()).toBeFalse(); + } + + function testIsError() external { + CommandResult memory result = commands.run(["forge", "--hlkfshjfhjas"]); + + expect(result.isError()).toBeTrue(); + } + + function testIsNotError() external { + CommandResult memory result = commands.run(["echo", "'Hello World'"]); + + expect(result.isError()).toBeFalse(); + } + + function testUnwrap() external { + CommandResult memory result = commands.run(["echo", "'Hello World'"]); + + bytes memory output = result.unwrap(); + + expect(string(output)).toEqual("'Hello World'"); + } + + function testUnwrapReverts() external { + CommandResult memory result = commands.run(["forge", "--hlkfshjfhjas"]); + + bytes memory expectedError = bytes( + string.concat( + "Failed to run command forge --hlkfshjfhjas:\n\n", + "error: unexpected argument '--hlkfshjfhjas' found\n\n", + "Usage: forge \n\n" "For more information, try '--help'.\n" + ) + ); + + ctx.expectRevert(expectedError); + + result.unwrap(); + } } diff --git a/test/_modules/Fe.t.sol b/test/_modules/Fe.t.sol new file mode 100644 index 00000000..35b9c4e7 --- /dev/null +++ b/test/_modules/Fe.t.sol @@ -0,0 +1,55 @@ +pragma solidity >=0.8.13 <0.9.0; + +import {Test, expect, commands, Command, fe, Fe, fs, println, strings} from "../../src/test.sol"; + +contract FeTest is Test { + function testToCommandAllSet() external { + string memory filePath = "./filePath.fe"; + Command memory command = + fe.create().setFilePath(filePath).setCompilerPath("difffe").setOutputDir("./feoutput").toCommand(); + + expect(command.inputs.length).toEqual(7); + expect(command.inputs[0]).toEqual("difffe"); + expect(command.inputs[1]).toEqual("build"); + expect(command.inputs[2]).toEqual("-e"); + expect(command.inputs[3]).toEqual("bytecode"); + expect(command.inputs[4]).toEqual("-o"); + expect(command.inputs[5]).toEqual("./feoutput"); + expect(command.inputs[6]).toEqual(filePath); + } + + function testToCommandMinimumSet() external { + string memory filePath = "./filePath.fe"; + + Command memory command = fe.create().setFilePath(filePath).toCommand(); + + expect(command.inputs.length).toEqual(7); + expect(command.inputs[0]).toEqual("fe"); + expect(command.inputs[1]).toEqual("build"); + expect(command.inputs[2]).toEqual("-e"); + expect(command.inputs[3]).toEqual("bytecode"); + expect(command.inputs[4]).toEqual("-o"); + expect(command.inputs[5]).toEqual("./out/__TMP/fe_builds"); + expect(command.inputs[6]).toEqual("./filePath.fe"); + } + + function testCompile() external { + fe.create().setFilePath("./test/mocks/guest_book.fe").setOutputDir("./test/fixtures/fe/output").setOverwrite( + true + ).build(); + + string memory result = fs.readFile("./test/fixtures/fe/output/A/A.bin"); + + expect(bytes(result).length).toBeGreaterThan(0); + } + + function testCompileAndRead() external { + Fe memory feCmd = fe.create().setFilePath("./test/mocks/guest_book.fe").setOverwrite(true); + + feCmd.build().unwrap(); + + string memory expectedBytecode = "600180600c6000396000f3fe00"; + + expect(string(feCmd.getBytecode("A"))).toEqual(expectedBytecode); + } +} diff --git a/test/_modules/Forks.t.sol b/test/_modules/Forks.t.sol index 3f6331c0..d7d09cfc 100644 --- a/test/_modules/Forks.t.sol +++ b/test/_modules/Forks.t.sol @@ -1,6 +1,6 @@ pragma solidity >=0.8.13 <0.9.0; -import {Test, expect, commands, forks, Fork, console} from "../../src/test.sol"; +import {Test, expect, commands, forks, Fork, CommandResult, println} from "../../src/test.sol"; import {Sender} from "../mocks/Sender.sol"; contract ForksTest is Test { @@ -9,12 +9,12 @@ contract ForksTest is Test { modifier skipIfEndpointFails() { string memory data = '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}'; - bytes memory res = commands.create("curl").args( + CommandResult memory res = commands.create("curl").args( ["--silent", "-H", "Content-Type: application/json", "-X", "POST", "--data", data, ENDPOINT] ).run(); - if (res.length == 0) { - console.log("Skipping test because forking endpoint is not available"); + if (res.stdout.length == 0) { + println("Skipping test because forking endpoint is not available"); return; } diff --git a/test/_modules/Huff.t.sol b/test/_modules/Huff.t.sol index 1dcb7665..f7673e39 100644 --- a/test/_modules/Huff.t.sol +++ b/test/_modules/Huff.t.sol @@ -1,6 +1,6 @@ pragma solidity >=0.8.13 <0.9.0; -import {Test, expect, Command, console, huff, Huffc} from "../../src/test.sol"; +import {Test, expect, Command, CommandResult, console, huff, Huffc} from "../../src/test.sol"; bytes32 constant SLOT = 0x0000000000000000000000000000000000000000000000000000000000000001; bytes32 constant OTHER_SLOT = 0x0000000000000000000000000000000000000000000000000000000000000002; @@ -53,7 +53,7 @@ contract HuffTest is Test { } function testCompile() external { - bytes memory initcode = huff.create().setFilePath("./test/mocks/Getter.huff").compile(); - expect(initcode.length).toBeGreaterThan(0); + CommandResult memory initcode = huff.create().setFilePath("./test/mocks/Getter.huff").compile(); + expect(initcode.stdout.length).toBeGreaterThan(0); } } diff --git a/test/mocks/guest_book.fe b/test/mocks/guest_book.fe new file mode 100644 index 00000000..004028c3 --- /dev/null +++ b/test/mocks/guest_book.fe @@ -0,0 +1,3 @@ +contract A { + target: address +}